目录
数据结构
数组在内存中是以一块连续的存储单元俩存储数据的,特点是查询快,删除插入慢。
查询的时间复杂度为O(1):数组存储的是固定类型的数据集合,如果声明为int数组,那么只能存储int类型的数据,所以它每一个数据所占的字节数是相同的,并且数组在内存中是连续的。当确定要找的数组下标,例如现在要查找1号数组下标(下标从0开始),按照数组查找公式 a[n]=起始地址+(n*字节数) 分析得到a[2] = 起始地址+2*4 即可找到(int占四个字节)。一次性就可以找到所需要的下标地址。所以时间复杂度为O(1)
删除和插入的时间复杂度为o(n):这里一个数组,现在想在0号和1号之间插入一个数字
将22插入之间
但是根据数组的定义这是一块连续的内存。所以数组下标都需要往后移动一位
所以插入和删除的时间复杂度为O(n),n一般是数组长度,因为如果是插入第一个,数组下标就需要移动n次,综合考虑n就为数组长度
一、一维数组
1、数组的定义
数组是一种容器,用来存储同种数据类型的多个值,存储的类型必须和容器的类型保持一致
2、数组的定义格式
格式一:数据类型 [] 变量名 范例 : int[] array;
格式二:数据类型 变量名 [] 范例 : int array []
- 以上两种类型推荐使用格式一,根据啊里开发手册,数据的定义方式使用的就是方式一
3、数组初始化概述
Java中的数组必须初始化然后才能进行使用。所谓初始化就是在内存中为数组容器开辟内存空间,并将数据存入容器的过程。
动态初始化
动态初始化是指初始化的时候,只为数组指定数组长度,由系统为数组分配初始值
默认值类型:
数据类型 | 默认值 |
整数 | 0 |
浮点数 | 0.0 |
布尔 | false |
字符 | 空字符 |
引用数据类型 | null |
格式: 数据类型[] 变量名= new 数据类型 [数组长度] 范例: int[] array = new int[5];
静态初始化
初始化时直接指定要存储的元素,系统还会自动计算出数组的长度
格式一: 数据类型[] 变量名 = new 数据类型[] {数据1,数据2,....} 范例 : int[] arr = new int[]{1,2,3}
格式二: 数据类型[] 变量名 ={数据1,数据2,....} 范例:int[] arr = {1,2,3}
- 特别说明的是,格式二中虽然没有new,但是java虚拟机会自动帮我们new出一块堆内存。
两种初始化方式的使用场景
动态初始化:适用于仅仅知道数组的长度,但是不知道数组的内容
静态初始化:知道了数组的具体内容,直接赋值
4、数据元素的访问
访问方式:数组名[索引] 范例:int[] arr = new int[3]; int i = arr[0];
索引是连续的从0开始的差值为1的数组容器中元素的下标
5、数组的遍历
先通过length获取数组的长度,然后通过for循环进行遍历
int[] arr ={1,2,3,4,5,6,7,8,9};
//先获取数组的长度
int length = arr.length;
//通过for循环根据数组索引进行遍历
for (int i =0;i<length;i++){
System.out.println(arr[i]);
}
6、数组操作中的常见问题
索引越界
访问数组中不存在得下标
int[] arr = {1,2,3};
System.out.println(arr[3]);
空指针异常
数组指向null
二、二维数组
1、数组的定义
二维数组也是一种容器,不同于一维数组的是,二维数组里面存储的是一维数组
2、数组的初始化
动态初始化:
格式:数据类型[][] 变量名 = new 数据类型[m][n] 范例:int[][] arr = new int [3][5] ;
说明:m代表二维数组中可以存放几个一维数组,n代表每个一维数组中可以存放多少个元素,范例为创建了一个可以容纳3个数组长度为5的一维数组
静态初始化:
格式一:数据类型[][] 变量名 = new 数据类型[][] {{x1,x2,x3},{y1,y2,y3}
范例:int[][] arr = new int [][] {{1,2,3},{4,5,6}} ;
格式二:数据类型[][] 变量名 ={{x1,x2,x3},{y1,y2,y3}
范例:int[][] arr = {{1,2,3},{4,5,6}} ;
3、数组存入数据的方式
方式一:将单个元素存入二维数组
int[][] arr = new int [3][2] ;
arr[0][0] = 1; //将1存入二维数组中第一个一维数组的0号索引
方式二:将整个一维数组存入二维数组
int[][] arr = new int [3][2] ;
arr[0] = new int [] {1,2,3};//将一个一维数作为二维数组的第一个数组
两种方式的一个细微的区别:
如果我们通过方式一在坐标为[0][2]存入一个元素是会发生索引越界异常的!
int[][] arr = new int [3][2] ;
arr[0][2]=1;
原因:在new int [3][2]的时候,我们已经在堆中指定好了一个能存放3个长度为2的一维数组,但是这时候却要在第一个一维数组的2号索引(就是下标第三个,索引是从0开始的0)存入一个值,然而这个索引是不存在的,所以肯定会出现索引越界
但是如果我们通过方式二直接存放一个长度为3的一维数组,这是允许的,不会发生异常,为什么明明二维数组规定了一维数组的长度只能为2,却可以存入一个长度为3的一维数组的?
int[][] arr = new int [3][2] ;
int[] a = new int[] {1,2,3};
arr[0]=a;
原因:在二维数组中,例如 arr [m][n], m存放的实际是是一维数组在堆中的内存地址,而n是一维数组的下标,如果我们通过arr[0]=a的方式赋值,实际是是将a这个一维数组的内存地址替换掉原来arr中第一个一维数组的地址.
2、二维数组的遍历
通过两次循环遍历,第一次循环获取一维数组,第二次循环遍历一维数组
int[][] arr = new int[][]{{1,2,3},{4,5,6},{7,8,9}};
for (int i =0;i<arr.length;i++){
for (int j =0;j<arr[i].length;j++){
System.out.print("---"+arr[i][j]);
}
System.out.println();
}