数组是一组相同数据类型元素的集合。在Java中数组属于引用类型,即数组是一个对象。
1. 一维数组
一维数组的定义
一维数组的两种声明方式:
数组元素类型 数组名字[];
数组元素类型[] 数组名字; //推荐使用
这种方式声明数组时并未给数组分配内存,因此还不能直接使用,需要使用构造函数new方法为数组分配内存,语法如下:
数组元素类型 数组名 = new 数组元素类型[数组元素个数]
eg:
int week[] = new int[7];
上面的代码创建了数组week,并指定数组长度为7,使用new关键字为数组分配内存时,整型数组中各个元素的初始值为0.
一维数组的初始化
有以下几种方式初始化一维数组
- 使用 new 指定数组大小后进行初始化
- 使用 new 指定数组元素的值
- 直接指定数组元素的值
代码例子:
// 使用 new 指定数组大小后进行初始化
int[] number = new int[5];
number[0] = 1;
number[1] = 2;
number[2] = 3;
number[3] = 4;
number[4] = 5;
// 使用 new 指定数组元素的值
int[] number = new int[] { 1, 2, 3, 4, 5 }; //不指定数组长度
// 直接指定数组元素的值
int[] number = { 1, 2, 3, 4, 5 };
易错点:
int[] number = new int[5] { 1, 2, 3, 4, 5 }; //注意,不能用这种方式初始化数组 ,语法错误
2. 二维数组
二维数组的定义
二维数组可当成两个一维数组,与一维数组的定义类似,二维数组也有两种声明方式:
数组元素类型 数组名字[][];
数组元素类型[][] 数组名字; //推荐使用
二维数组初始化方法与一维数组类似
来看代码:
public static void main(String[] args){
int[][] a = { {1,2,3},{4,5,6} }; //直接给二维数组赋值
int[][] a1= new int[][]{ {1,2,3}, {4,5,6} }; //使用构造函数初始化二维数组
//分别给第一行和第二行的一维数组赋值
int[][] a= new int[2][3];
a[0] = new int[]{1,2,3};
a[1] = new int[]{4,5,6};
}
二维数组的两个下标,左索引决定行,由索引决定列。
二维数组的内存分配: 以 int[][] a = new int[2][3]; 为例
3. 数组的使用
数组的常用操作:遍历、排序、查询、复制等,下面以几个经典例子来进行说明。
1. 冒泡排序
算法思想:数组内的元素两两比较,将最大的元素放到最后(或最前)
public static void main(String[] args){
int arr[] = {88,1,9,22,99,6,100,6,35};
for(int i=0;i < arr.length-1;i++) {//外层循环控制排序趟数
for(int j=0; j< arr.length-i-1;j++) {
//内层循环控制每一趟排序多少次
// 把小的值交换到前面
if (arr[j]>arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
System.out.print("第"+(i+1)+"次排序结果:");
//列举每次排序的数据
for(int a=0;a<arr.length;a++) {
System.out.print(arr[a] + "\t");
}
System.out.println("");
}
System.out.println("最终排序结果:");
for(int a = 0; a < arr.length;a++) {
System.out.println(arr[a] + "\t");
}
}
结果:
第1次排序结果:1 9 22 88 6 99 6 35 100
第2次排序结果:1 9 22 6 88 6 35 99 100
第3次排序结果:1 9 6 22 6 35 88 99 100
第4次排序结果:1 6 9 6 22 35 88 99 100
第5次排序结果:1 6 6 9 22 35 88 99 100
第6次排序结果:1 6 6 9 22 35 88 99 100
第7次排序结果:1 6 6 9 22 35 88 99 100
第8次排序结果:1 6 6 9 22 35 88 99 100
最终排序结果:
1
6
6
9
22
35
88
99
100
2. 选择排序
算法思想:将指定排序位置的元素与其他位置元素分别比较,找出最大的(或最小的)放到最后(或最前)
public static void main(String[] args) {
int[] arr = new int[]{88,1,9,22,99,6,100,6,35};
// int index;
for (int i =0; i<arr.length-1; i++) {
int index = 0;
for (int j =1; j<=arr.length-i-1; j++) {
if (arr[j]>=arr[index]) { //找出数组中最大的一个数
index = j; //指针指向最大的元素
}
}
int tmp = arr[arr.length-i-1];
arr[arr.length-i-1] = arr[index]; //将最大的数放到最后
arr[index] = tmp;
}
System.out.println("选择排序的结果:");
for (int a:arr) { //foreach遍历
System.out.println(a);
}
}
选择排序的结果:
1
6
6
9
22
35
88
99
100
3. 反转排序
算法思想:将数组两边的元素进行替换。
public static void main(String[] args) {
int[] arr = new int[]{88,1,9,22,99,6,100,6,35};
System.out.println("初始数组:");
for (int a:arr) {
System.out.print(a + "\t");
}
System.out.println("");
for (int i =0; i<arr.length/2; i++) {
int tmp = arr[i];
arr[i] = arr[arr.length-i-1]; //反序交换元素值
arr[arr.length-i-1] = tmp;
}
System.out.println("反转排序的结果:");
for (int a:arr) {
System.out.print(a + "\t");
}
}
结果:
初始数组:
88 1 9 22 99 6 100 6 35
反转排序的结果:
35 6 100 6 99 22 9 1 88
三种排序方式的比较:
1)冒泡排序
时间复杂度:O(n^2)
- 最好情况:已经排完序,为O(n)
- 最坏情况:逆序排列,为O(n^2)
- 平均情况:O(n^2)
空间复杂度:O(1)
- 冒泡排序在原地排序,只需要常数级别的辅助空间,因此空间复杂度为O(1)。
内存占用情况:
- 冒泡排序也是一种比较消耗内存的算法,因为它需要在排序过程中不断交换相邻的元素,每次交换都需要使用一个临时变量来存储数据,因此它的内存占用情况较高。
2)选择排序
时间复杂度:O(n^2)
- 最好情况和最坏情况时间复杂度都为O(n^2)
- 平均情况:O(n^2)
空间复杂度:O(1)
- 选择排序也是一种原地排序的算法,只需要常数级别的辅助空间,因此空间复杂度为O(1)。
内存占用情况:
- 相对于冒泡排序,选择排序的内存占用情况要略低一些,因为它只需要选择最小的元素,并将其与第一个元素进行交换,而不需要像冒泡排序一样不断交换相邻的元素,因此它的内存占用情况较低。
3)反序排序
时间复杂度:O(n)
- 反序排序只需要对已经排完序的数据进行一次翻转,因此时间复杂度为O(n)。
空间复杂度:O(1)
- 反序排序也是一种原地排序的算法,只需要常数级别的辅助空间,因此空间复杂度为O(1)。
内存占用情况:
- 反序排序在排序过程中并没有进行任何的比较和交换操作,因此它的内存占用情况非常低。
总的来说,这3种排序方法都是原地排序算法,冒泡排序和选择排序时间复杂度均为O(n^2),空间复杂度均为O(1),内存占用情况较高;而反序排序时间复杂度为O(n),空间复杂度为O(1),内存占用情况非常低。