数组概述
- 数组(Array),是多个相同类型数据按一定顺序排列的集合,并使用一个名字命名,并通过编号的方式对这些数据进行统一管理。
- 数组本身是引用数据类型,而数组中的元素可以是任何数据类型,包括基本数据类型和引用数据类型。
- 创建数组对象会在内存中开辟一整块连续的空间,而数组名中引用的是这块连续空间的首地址。
- 数组的长度一旦确定,就不能修改。
- 我们可以直接通过下标(或索引)的方式调用指定位置的元素,速度很快。
- 数组的分类:按照维度:一维数组、二维数组、三维数组、…;按照元素的数据类型分:基本数据类型元素的数组、引用数据类型元素的数组(即对象数组)
一维数组的使用
- 一维数组的声明和初始化
//数组声明 int[] ids; //静态初始化:数组的初始化和赋值操作同时进行 ids = new int[]{1000,1100}; //简写,只有声明和赋值在同一行时可以简写 int[] ids = {1000,1100}; //动态初始化:数组的初始化和赋值操作分开进行 String[] names = new Sting[5]; //其他,括号在后也可以 String names[]=new String[5]; //不管使用哪种方法,初始化完成,数组长度就确定了 //数组的声明只能使用一种,多用少用都会报错 int[] arr1 = new int[];//报错 int[] arr2 = new int[2]{1,2};//报错
- 获取一维数组的长度
String[] names = new String[5]; System.out.println(names.length);
- 各种类型数组的默认值
- 整型:0
- 浮点型:0.0
- char型:0或‘\u0000’(ASCII码中的0,不是‘0’)
- Boolean型:false
- String型(引用型):null(指空,不是“null”) - 一维数组的内存解析
内存简化结构
二维数组内存解析
二维数组的使用
- 二维数组的声明和初始化
//静态初始化 int[][] arr = new int[][]{{1,2,3},{1,2},{1}}; //动态初始化 int[][] arr2 = new int[3][2]; int[][] arr3 = new int[3][]; //简写 int[][] arr4 = {{1,2,3},{1,2}}; //其他,括号在后也可以 int[] arr5[] = {{1,2,3},{1,2}}; int arr6[][] = new int{{1,2,3},{1,2}}; //不像矩阵一样要求行列统一,每个数组的长度可以不一样,动态初始化时可以只赋前一个值 //错误情况,可以只赋前一个,不能只赋后一个 int[][] arr6 = new int[][4];
- 二维数组中元素的引用
//与一维数组类似,但需要两个索引 int[][] arr = new int[][]{{1,2,3},{1,2},{1}}; System.out.println(arr[0][2]);//输出 3 //当初始化只声明了前一个长度时,用两个索引会报空指针 int[][] arr1 = new int[3][]; System.out.println(arr1[0][2]); //取arr1[0],此时取到的是空数组,再用空数组取取值,则报空指针异常
- 获取二维数组的长度
int[][] arr = new int[][]{{1,2,3},{1,2},{1}}; System.out.println(arr.length);//输出 3 System.out.println(arr[1].length);//输出 2
- 二维数组的默认值
- 初始化时两个长度都有
//外层初始值为一个地址值,内层与一维数组相同 int[][] arr =new int[3][2]; System.out.println(arr[0]);//输出[I@8efb846 System.out.println(arr[0][0]);//输出 0
- 初始化时只赋了前一个长度
//外层初始值为null,内层调用会报错 int[][] arr =new int[3][]; System.out.println(arr[0]);//输出 null System.out.println(arr[0][0]);//报空指针
- 二维数组的内存解析
- 初始化时两个长度都有
二维数组内存解析
常见算法
- 杨辉三角
//初始化数组 int [][] yangHui = new int [10][]; for (int i = 0;i< yangHui.length;i++){ yangHui[i]= new int[i+1]; //给每个数组的第一个和最后一个赋1 yangHui[i][0] = 1; yangHui[i][i] = 1; //其余的值用上方和上方的左边相加得到 if (i>1) { for (int j = 1;j<yangHui[i].length-1;j++) { yangHui[i][j] = yangHui[i-1][j-1]+yangHui[i-1][j]; } } } //遍历二维数组,并打印 for (int i = 0;i<yangHui.length;i++) { for (int j = 0;j<yangHui[i].length;j++) { System.out.print(yangHui[i][j]+" "); } System.out.println(); }
杨辉三角运行结果
- 回文数字
int max = 5; //数组初始化 int[][] huiWen = new int[max][max]; int minX = 0; int maxX = max - 1; int minY = 0; int maxY = max - 1; int count = 0; while (minX <= maxX) { for (int i = minY;i <= maxY;i++) { huiWen[minX][i] = ++count; } minX++; for (int i = minX;i <= maxX;i++) { huiWen[i][maxY] = ++count; } maxY--; for (int i = maxY;i >=minY;i--) { huiWen[maxX][i] = ++count; } maxX--; for (int i = maxX;i >= minX;i--) { huiWen[i][minY] = ++count; } minY++; } for (int i = 0;i<huiWen.length;i++) { for (int j = 0;j<huiWen[i].length;j++) { //为了输出更美观 if(i == 0) { System.out.print(huiWen[i][j]+" "); }else { System.out.print(huiWen[i][j]+" "); } } System.out.println(); }
回文数字运行结果
-
数组的复制
int[] array1=new int[]{1,2,3,4}; int[] array2=new int[array1.length]; for (int i = 0;i < array1.length;i++){ array2[i] = array1[i]; } //这并不能算复制,这只是把array1的空间地址给了array2,相当于创建了一个快捷方式 int[] array2 = array1
-
二分法查找(需要数组有序)
int[] arr3 = new int[]{-99,-54,-2,0,2,33,43,256,999}; boolean isFlag = true; int number = 256; //int number = 25; int head = 0;//首索引位置 int end = arr3.length - 1;//尾索引位置 while(head <= end){ int middle = (head + end) / 2; if(arr3[middle] == number){ System.out.println("找到指定的元素,索引为:" + middle); isFlag = false; break; }else if(arr3[middle] > number){ end = middle - 1; }else{//arr3[middle] < number head = middle + 1; } } if(isFlag){ System.out.println("未找打指定的元素"); }
-
排序算法
- 衡量排序算法的优劣:1.时间复杂度:分析关键字的比较次数和记录的移动次数;2.空间复杂度:分析排序算法中需要多少辅助内存;3.稳定性:若两个记录A和B的关键字值相等,但排序后A、B的先后次序保持不变,则称这种排序算法是稳定的。
- 排序算法分类:1.内部排序:整个排序过程不需要借助于外部存储器(如磁盘等),所有排序操作都在内存中完成。2.外部排序:参与排序的数据非常多,数据量非常大,计算机无法把整个排序过程放在内存中完成,必须借助于外部存储器(如磁盘)。外部排序最常见的是多路归并排序。可以认为外部排序是由多次内部排序组成。
- 十大内部排序算法
十大内部排序算法
排序算法的比较- 冒泡排序
int[] arr = new int[]{43,32,79,5,65,12,55,122}; for(int i = 0;i < arr.length - 1;i++){ for(int j = 0;j < arr.length - 1 - i;j++){ if(arr[j]>arr[j+1]){ int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } }
- 快速排序
public void subSort(int[] data,int start,int end){ if(start < end){ int base = data[start]; int low = start; int high = end + 1; //要保证比较完后索引与比较的数的索引保持一致,所以要错位和先 while(true){ while(low < end && data[++low] - base <= 0) ; while(high > start && data[--high] - base >= 0) ; if(low < high){ swap(data,low,high); }else{ break; } } swap(data,start,high); subSort(data,start,high - 1); subSort(data,high + 1,end); } }
- Arrays工具类的使用
import java.util.Arrays; //判断两个数组是否相等 boolean isEquals=Arrays.equals(arr1,arr2); //打印数组内容 Arrays.toString(arr1); //将数组中所有元素赋成一个值 Arrays.fill(arr1,10); //快速排序 Arrays.sort(arr1); //二分查找(未找到返回负数) int index = Arrays.binarySearch(arr1,10);
特别地
int[] arr =new int[]{1,2,3};
char[] arr1 = new char[]{'a','b','c'};
System.out.println(arr)
//一个地址值
System.out.println(arr1)
//a b c
//对于一般的数组,打印时引用的是println(Object x),该方法直接打印变量,故打印地址值;对于char数组有一个专门的重载方法,println(char[] a),该方法会遍历数组并打印元素