从零开始学数组🔄:深入浅出,带你掌握核心要点

简介: 【2月更文挑战第1天】

数组理论基础

数组是存放在连续内存空间上的相同类型数据的集合。

数组是一种线性表结构,线性表结构,顾名思义就是,将存储的数据排成一条线一样的结构,存储的每个数据最多只有前后两个方向。

因为数组的在内存空间的地址是连续的,使得数组按照下标随机访问(随机访问:可以用同等的时间访问到一组数据中的任意一个元素)数组中数据元素时间复杂度达到 O(1) 级别。

计算机会为每一个内存单元分配一个地址,并通过该地址来访问内存中的数据。数组在内存空间中的地址是连续的,当我们知道数据的首地址后,通过公式便可以计算出元素的内存地址,让计算机直接访问,达到 O(1) 级别的时间复杂度。

我们是通过数组下标访问数据时,时间复杂度才是 O(1),

当我们通过数据查找元素时,我们需要遍历数组查找对应的数据,时间复杂度是 O(n)。

// i 表示数组下标, base_address 表示数组首地址,data_type_size 表示数组中每个数据大小
a[i]_address=base_address+i*data_type_size

但是我们在删除或者增添元素的时候,就难免要移动其他元素的地址。

例如 删除下标为3的元素,需要对下标为3的元素后面的所有元素都要做移动操作,如图所示:

数组具有以下特点:

  • 在存储空间中按顺序存储,地址连续。
  • 数值数组元素的默认值为 0,而引用元素的默认值为 null。
  • 数组的索引从 0 开始,如果数组有 n 个元素,那么数组的索引是从 0 到(n-1)。
  • 数组元素可以是任何类型,包括数组类型。
  • 数组的元素是不能删的,只能覆盖平时删除操作也是依次用后一位覆盖,因为申请且初始化后,存储空间就固定了。

数组变量的声明

首先必须声明数组变量,才能在程序中使用数组。

dataType[] arrayRefVar;   // 首选的方法
 
 
dataType arrayRefVar[];  // 效果相同,但不是首选方法

数组的创建

创建数组的方式
array =new dataType[arraySize];
dataType[] array={value0,value1,....,valuen};

array =new dataType[arraySize];

代码分析

1、使用dataType[arraySize]创建一个数组。

2、把新创建的数组引用赋值给变量array。

数组变量的声明并创建数组;

dataType[] array=new dataType[arraySize];

数组遍历

数组创建后,元素类型和数组的大小都是确定的。遍历数组时可以选取for循环或者For-Each循环

for循环

double[] arr={1.1,2.2,3.3};
        for (int i=0;i<arr.length;i++){
            System.out.println(arr[i]);
        }

For-Each循环

For-Each 循环或者加强型循环,它能在不使用下标的情况下遍历数组。

for (double element:arr
             ) {
            System.out.println(element);
        }

多维数组

二维数组可以看成是数组的数组,三维数组可以看成二维数组的数组。

比如二维数组就是一个特殊的一维数组,其每一个元素都是一个一维数组。

多维数组声明

数据类型[][] 数组名称;
数据类型[]   数组名称[];
数据类型     数组名称[][];
int[][] array;
char arrays[][];
数据类型[][][] 数组名称;
多维数组声明以此类推。

数组声明以后在内存中没有分配具体的存储空间,也没有设定数组的长度。

Java 中多维数组不必都是规则矩阵形式,例如 int[][] arr = new int[][]{{1, 1, 2}, {2, 5}, {1, 2, 3, 4}};

注意:int[] x,y[]:  x是一维数组,y 是二维数组。

多维数组初始化

  1. 静态初始化(整体赋值)

数组静态初始化时,必须和数组的声明写在一起。

int[][] arrays = {{ 1, 2, 3, 4 }, { 5, 6, 7, 8 },{ 9, 10, 11, 12 }};
//定义一个名称为 arrays 的二维数组,二维数组中有三个一维数组,每一个一维数组中具体元素也都初始化了。
int[][][] arrays2 = { { {1,2,3} , {1,2,3} } ,{{3,4,1},{2,3,4}} };
//定义一个名称为 arrays2 的三维数组,三维数组中有两个二维数组,每个二维数组中有两个一维数组,每一个一维数组中具体元素也都初始化了。
  1. 动态初始化
数据类型[][] 数组名称= new 数据类型[第一维的长度][第二维的长度];
数据类型[][] 数组名称;
数组名称= new 数据类型[第一维的长度][第二维的长度];
int[][] array=new int[2][2];
int [][] arrays;
arrays=new int[3][4];

动态初始化可以和数组的声明分开,动态初始化只指定数组的长度,数组中每个元素的初始化是数组声明时数据类型的默认值。

int[][] a=new int [2][3];

int[][] b;

b=new int [1][2];

这种初始化方式的数组中,第二维长度都是相同的。也可以从最高维开始,分别为每一个维度分配空间。

String[][]s = newString[2][];

s[0] = newString[2];

s[1] = newString[3];

所以,在初始化第一维的长度时,其实是将数组看成了一个一维数组,初始化长度为2,而该数组包含2个元素,这两个元素分别也是一个一维数组。

Java 中多维数组不必都是规则矩阵形式,每个一维数组的长度可以各不相同。

C++中⼆维数组在地址空间上是连续的。像Java是没有指针的,同时也不对程序员暴露其元素的地址,寻址操作完全交给虚拟机。

这⾥的数值也是16进制,这不是真正的地址,⽽是经过处理过后的数值了,我们也可以看出,⼆维数组的每⼀⾏头结点的地址是没有规则的,更谈不上连续。

Java的⼆维数组可能是如下排列的⽅式:

数组默认值(以二维数组为例)

二维数组分为外层数组的元素,内层数组的元素,例如外层元素:arr[1]等 ,内层元素:arr[1][2]等

数组元素的默认初始化值:

  • 针对于初始化方式一:比如:int[][] arr = new int[4][3];

外层元素的初始化值为:内层数组的地址值。

内层元素的初始化值为:与一维数组初始化情况相同

一维数组的默认值取决于数组元素的类型。以下是一些常见类型的默认值:

  • 对于整数类型(如int、byte、short、long),默认值为0。
  • 对于浮点数类型(如float、double),默认值为0.0。
  • 对于布尔类型(boolean),默认值为false。
  • 对于字符类型(char),默认值为\u0000,即空字符。
  • 对于引用类型(如类、接口、数组),默认值为null,表示没有引用任何对象
  • 针对于初始化方式二:比如:int[][] arr = new int[2][];

外层元素的初始化值为: null

内层元素的初始化值为:不能调用,否则报错。

多维数组的长度

//多维数组的长度
int[][] m = {{1,2,3,1},{1,3},{3,4,2}};
int sum=0;
for (int i=0;i<m.length;i++){
    sum+=m[i].length;
 }
System.out.println("sum="+sum);

遍历多维数组(以二维数组为例)

对二维数组中的每个元素,引用方式为 arrayName[index1][index2],例如:num[1][0]

for循环遍历

for (int i=0;i<m.length;i++){
            for (int j=0;j<m[i].length;j++){
                System.out.println(m[i][j]);
            }
            System.out.println();
        }

foreach循环遍历

for (int[] type:m  ) // 第一个循环,第一个参数代表循环中的类型,即数组,第二个参数为循环对象
{
  for (int j:type) {System.out.println(j); }// 循环上一个循环中的第一个参数中的每一个即可
    System.out.println();
}
目录
相关文章
|
4月前
|
算法 Java 编译器
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】-3
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】
39 0
|
4月前
|
算法 Java 编译器
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】-1
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】
109 3
|
4月前
|
存储 编译器 程序员
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】-2
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】
62 0
|
30天前
|
程序员 Python
类的设计奥秘:从代码到架构的科普全解
类的设计奥秘:从代码到架构的科普全解
13 2
|
30天前
|
Python
继承概念深度解析:代码视角下的科普之旅
继承概念深度解析:代码视角下的科普之旅
6 0
|
4月前
|
安全 编译器 程序员
【C++】万字一文全解【继承】及其特性__[剖析底层化繁为简](20)
【C++】万字一文全解【继承】及其特性__[剖析底层化繁为简](20)
|
6月前
|
机器学习/深度学习 人工智能 算法
这篇科普让你Get所有大模型的基础核心知识点
本文介绍了AI大模型的概念和发展历程。AI大模型是指具有1亿以上参数的机器学习模型,通过在大规模数据集上进行预训练,可以直接支撑各类应用。大模型的发展经历了从萌芽期到AI1.0时期,再到AI2.0时期的飞跃,目前最新发布的大模型参数已经达到了千亿甚至万亿级别。国内外的公司都在积极研发和应用大模型,如OpenAI、Google、Facebook、Microsoft等。国内也有百度、阿里巴巴、万维、商汤科技等公司发布了自己的大模型产品。大模型的建造离不开算力资源、算法人才、数据积累等核心要素。此外,文章还列举了一些与大模型相关的专业名词,如算法、模型参数、训练数据、Token等。
|
7月前
|
前端开发 NoSQL 数据库
项目重点知识点详解
项目重点知识点详解
|
9月前
|
前端开发
项目实战典型案例22——原型图的面向对象思路
项目实战典型案例22——原型图的面向对象思路
49 1
|
9月前
|
SQL 前端开发 Java
项目实战典型案例6——没有复用思想
项目实战典型案例6——没有复用思想
47 0