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

简介: 【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();
}
目录
相关文章
|
7月前
|
存储 算法 Java
Java集合框架知识点学习核心总结
Java集合框架包含Collection、List(ArrayList、LinkedList)、Set(HashSet、TreeSet)、Map(HashMap、TreeMap)接口及迭代器、泛型、比较器。迭代器用于遍历集合,泛型避免类型转换,比较器用于元素比较。集合框架还提供排序、查找、去重算法。Java 8新增Stream API、Lambda表达式和Optional类,提升集合操作效率。
55 6
|
算法 Java 编译器
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】-1
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】
292 3
|
算法 Java 编译器
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】-3
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】
73 0
|
人工智能 分布式计算 Java
【C++初阶】前言——C++的发展简述及学习方法分享
之前我们一直分享C语言和使用C语言完成数据结构的初阶的文章,今天我们正式进入C++的学习,这篇文章主要是给大家带来的是C++的由来、以及和C语言的区别、更主要的是和大家分享自己的学习方法,给一些我的建议。
|
1月前
|
自然语言处理 安全 PHP
深入浅出PHP编程:从基础到实战
【10月更文挑战第36天】本文将带你走进PHP的奇妙世界,无论你是初学者还是有一定经验的开发者,都将从中获益。文章首先介绍PHP的基础概念和语法,然后通过实际代码示例,展示如何利用PHP进行高效的Web开发。最后,我们将探讨一些高级主题,如面向对象编程、数据库操作以及安全性问题。让我们一起开启PHP的学习之旅吧!
|
存储 编译器 程序员
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】-2
C++ | 深入浅出类的封装思想【图文案例,通俗易懂】
386 0
|
4月前
|
存储 API 数据库
深入浅出理解后端开发:从概念到实践
【8月更文挑战第31天】本文将带您走进后端开发的神秘世界,一步步解析后端开发的核心概念、技术栈选择、以及实际开发中的代码实践。我们将通过一个简易的待办事项列表API的开发过程,展示如何从零开始构建一个后端服务,包括数据库设计、RESTful API实现及部署流程。无论您是初学者还是希望深化理解,这篇文章都将为您提供清晰的指导和实用的知识。
|
6月前
|
安全 网络安全
Day1:360培训学习重点笔记(7.13)
Day1:360培训学习重点笔记(7.13)
|
7月前
|
存储
🚀链表理论:基础概念与实战技巧!
【2月更文挑战第8天】
166 43
|
7月前
|
机器学习/深度学习 存储 人工智能
数据结构与算法设计:深度解析与实践
数据结构与算法设计:深度解析与实践
149 0