数组排序
数组排序指的是让一堆杂乱无章的数据,按从小到大排列,或者按从大到小排列,让其有规律。这个过程就是数组排序。排序的算法很多,例如:冒泡排序,选择排序,快速排序,归并排序,插入排序等等。咱们讲一下冒泡排序和选择排序。
冒泡排序
冒泡排序:海底的气泡由于水压的作用,越深的地方气泡就越小,气泡在上浮的过程中,由于水压的减小,气泡会越来越大,到达海面的时候,气泡会最大。基于这个启发,数学家们发明了冒泡排序。
冒泡排序的思想:以从小到大排序为例。依次比较相邻的2个数据,如果前面的数据大于后面的数据,二者交换位置,一趟下来之后,最大的数据就跑到了末尾,这个数据在下一趟不再参与比较。第二趟仍然是依次比较相邻的2个数据,如果前面的数据大于后面的数据,二者交换位置,第二趟下来之后,第2大的数据就跑到了倒数第二位,同样这个数据不再参与下一趟的比较,以此类推,对于具有n个数的数组而言,进行n-1趟上述过程,就能让数组有序。
1. 需求:有如下一组数{67, 42, 88, 16, 25, 3},对其按从小到大的顺序排列。
2. 代码:
public static void main(String[] args) {
//需求:有如下一组数{67, 42, 88, 16, 25, 3},对其按从小到大的顺序排列。
//分析:
//1.创建一个数组保存上述数据
//2.使用冒泡法进行排序
//原始数据 67 42 88 16 25 3------一共6个数据,共比较5趟
//第1趟,一共比较5次
// 第1次 42 67 88 16 25 3
// 第2次 42 67 88 16 25 3
// 第3次 42 67 16 88 25 3
// 第4次 42 67 16 25 88 3
// 第5次 42 67 16 25 3 88-----88不再参与下一轮比较。第1趟找出了最大值
//第2趟,一共比较4次
// 第1次 42 67 16 25 3 88
// 第2次 42 16 67 25 3 88
// 第3次 42 16 25 67 3 88
// 第4次 42 16 25 3 67 88-----67和88不再参与下一轮比较,第2趟找出了第2大值。
//第3趟,一共比较3次
// 第1次 16 42 25 3 67 88
// 第2次 16 25 42 3 67 88
// 第3次 16 25 3 42 67 88-----42,67,88不再参与下一轮比较,第3趟找出了第3大值
//第4趟,一共比较2次
// 第1次 16 25 3 42 67 88
// 第2次 16 3 25 42 67 88-----25,42,67,88不再参与下一轮比较,第4趟找出了第4大值
//第5趟,一共比较1次
// 第1次 3 16 25 42 67 88-----全部数据有序。
int[] array = {67, 42, 88, 16, 25, 3};
for (int i = 0; i < array.length - 1; i++) {
for (int j = 0; j < array.length - 1 - i; j++) {
if (array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
冒泡排序的格式也很固定:
for(int i = 0; i < 数组名.length - 1; i++){
for(int j = 0; j < 数组名.length - 1 - i; j++){
if(数组名[j] > 数组名[j+1]){
数据类型 temp = 数组名[j];
数组名[j] = 数组名[j+1];
数组名[j+1] = temp;
}
}
}
选择排序
选择排序思想:以从小到大排序为例。第一趟,从数组中找出最小值,并记录最小值的下标,让最小值与数组下标为0的元素交换位置。第二趟,刨除数组下标为0的元素,在剩下的元素中找出最小值,并记录最小值的下标,与数组下标为1的元素交换位置。第三趟,刨除数组下标为0和1的元素,在剩下的元素中找出最小值,并记录最小值的下标,与数组下标为2的元素交换位置,以此类推,如果要对n个数排序,n-1趟即可让数组有序。
1. 需求:有如下一组数{67, 42, 88, 16, 25, 3},对其按从小到大的顺序排列。
2. 代码:
public static void main(String[] args) {
//需求:有如下一组数{67, 42, 88, 16, 25, 3},对其按从小到大的顺序排列。
//分析:
//1.创建一个数组保存上述数据
//2.定义变量index保存最小值的下标。
//3.使用选择排序法进行排序
//原始数据 67 42 88 16 25 3------一共6个数据,共比较5趟
//第1趟,一共比较5次 假定下标为0的元素是最小值。即index初始值是0
// 第1次 67 42 88 16 25 3 下标为1的和下标为index的比较,下标为1的更小,将index更新为1
// 第2次 67 42 88 16 25 3 下标为2的和下标为index的比较,下标为index比较小,不更新index
// 第3次 67 42 88 16 25 3 下标为3的和下标为index的比较,下标为3的更小,将index更新为3
// 第4次 67 42 88 16 25 3 下标为4的和下标为index的比较,下标为index比较小,不更新index
// 第5次 67 42 88 16 25 3 下标为5的和下标为index的比较,下标为5的更小,将index更新为5
// 第1趟结束后,最小的元素已经找到,即下标为5的元素,让下标为5的元素和下标为0的元素交换位置。
// 3 42 88 16 25 67---最小值就找出来了。最小值不再参与下一趟比较。
//第2趟,一共比较4次 假定下标为1的元素是最小值。即index初始值是1
// 第1次 3 42 88 16 25 67 下标为2的和下标为index的比较,下标为index比较小,不更新index
// 第2次 3 42 88 16 25 67 下标为3的和下标为index的比较,下标为3的更小,将index更新为3
// 第3次 3 42 88 16 25 67 下标为4的和下标为index的比较,下标为index比较小,不更新index
// 第4次 3 42 88 16 25 67 下标为5的和下标为index的比较,下标为index比较小,不更新index
// 第2趟结束后,第二小的元素已经找到,即下标为3的元素,让下标为3的元素和下标为1的元素交换位置。
// 3 16 88 42 25 67---最小值和次小值就找出来了。二者不再参与下一趟比较。
//第3趟,一共比较3次 假定下标为2的元素是最小值。即index初始值是2
// 第1次 3 16 88 42 25 67 下标为3的和下标为index的比较,下标为3的更小,将index更新为3
// 第2次 3 16 88 42 25 67 下标为4的和下标为index的比较,下标为4的更小,将index更新为4
// 第3次 3 16 88 42 25 67 下标为5的和下标为index的比较,下标为index比较小,不更新index
// 第3趟结束后,第三小的元素已经找到,即下标为4的元素,让下标为4的元素和下标为2的元素交换位置。
// 3 16 25 42 88 67---最小的3个数就找出来了。三者不再参与下一趟比较。
//第4趟,一共比较2次 假定下标为3的元素是最小值。即index初始值是3
// 第1次 3 16 25 42 88 67 下标为4的和下标为index的比较,下标为index比较小,不更新index
// 第2次 3 16 25 42 88 67 下标为5的和下标为index的比较,下标为index比较小,不更新index
// 第4趟结束后,第四小的元素已经找到,即下标为3的元素,让下标为3的元素和下标为3的元素交换位置。
// 3 16 25 42 88 67---最小的4个数就找出来了。四者不再参与下一趟比较。
//第5趟,一共比较1次 假定下标为4的元素是最小值。即index初始值是4
// 第1次 3 16 25 42 88 67 下标为5的和下标为index的比较,下标为5的更小,将index更新为5
// 第5趟结束后,第五小的元素已经找到,即下标为5的元素,让下标为5的元素和下标为4的元素交换位置。
// 3 16 25 42 67 88---至此,数据全部有序。
int[] array = {67, 42, 88, 16, 25, 3};
for (int i = 0; i < array.length - 1; i++) {
int index = i;
for (int j = i + 1; j < array.length; j++) {
if (array[j] < array[index]) {
index = j;
}
}
if (index != i) {
int temp = array[index];
array[index] = array[i];
array[i] = temp;
}
}
for (int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
选择排序的写法很固定:
for(int i = 0; i < 数组名.length - 1; i++){
int index = i;
for(int j = i + 1; j < 数组名.length; j++){
if(数组名[j] < 数组名[index]){
index = j;
}
}
if(index != i){
数据类型 temp = 数组名[i];
数组名[i] = 数组名[index];
数组名[index] = temp;
}
}
二维数组
数组是一个容器,可以存放数据。不仅可以存放基本数据类型,还可以存放引用类型,即数组的元素可以是数组。如果一个数组的元素是数组,这样就构成了一个二维数组。
数组存放普通数据:
数组存放数组:
二维数组的定义
二维数组的定义格式和一维数组的定义类似,分为2种:推荐使用格式一
格式一:数据类型 [] [] 数组名
示例:int [] [] arr
含义:定义了一个整型的二维数组,数组名是arr。
格式二:数据类型 数组名[] []
含义:定义了一个整型的二维数组,数组名是arr。
二维数组的初始化
二维数组的初始化也分为:动态初始化 和 静态初始化
动态初始化
动态初始化格式:
数据类型[] [] 数组名 = new 数据类型[第一维元素个数] [第二维元素个数];
示例:int[] [] arr = new int[4] [3];
含义:定义了一个4行3列的二维数组,数组中每个元素的初始值是0。
静态初始化
静态初始化格式:
数据类型[] [] 数组名 = new 数据类型[] []{ {值1,值2,值3..} ,{值1,值2,值3..} ,..};
示例:int[] [] arr = new int[] [] {{8, 22, 35, 17},{13, 9, 26, 21}};
含义:定义了一个2行4列的二维数组,数组的初始值是:8, 22, 35, 17, 13, 9, 26, 21
静态初始化的简化格式:
数据类型[] [] 数组名 = { {值1,值2,值3..} ,{值1,值2,值3..} ,..};
示例:int[] [] arr = {{8, 22, 35, 17},{13, 9, 26, 21}};
含义:定义了一个2行4列的二维数组,数组的初始值是:8, 22, 35, 17, 13, 9, 26, 21
二维数组的使用场景
1. 游戏的地图
2. 游戏里的背包、储物柜
3. 彩票购买软件里,多注彩票的存储
4. 修图软件里图片的像素
...
二维数组的访问
访问二维数组
数组名代表整个二维数组。数组名存储的是整个二维数组的起始地址。
如果打印数组名,将会显示一个地址值。
给数组名赋值,将改变二维数组的指向。
public static void main(String[] args) {
int[][] arr = {{8, 22, 35, 17},{13, 9, 26, 21}};
System.out.println(arr);//二维数组在堆区的起始地址
}
访问第一维(行)
语法格式:数组名[第一维的下标]
由于二维数组可以看成1个元素是数组的一维数组。因此 数组名[第一维的下标] 获取的是内层数组的地址。
如果打印 数组名[第一维的下标] 得到的是一个地址值。
public static void main(String[] args) {
int[][] arr = {{8, 22, 35, 17},{13, 9, 26, 21}};
System.out.println(arr);//二维数组在堆区的起始地址
System.out.println(arr[0]);//二维数组第1行元素在堆区的起始地址
System.out.println(arr[1]);//二维数组第2行元素在堆区的起始地址
}
二维数组元素的访问
语法格式: 数组名[第一维的下标] [第二维的下标]
示例: arr[1] [2]
含义:访问的是二维数组第2行第3列的元素。
数组名[第一维的下标] [第二维的下标] 可以看成是一个特殊的变量,因此可以对其进行赋值和取值。
public static void main(String[] args) {
int[][] arr = {{8, 22, 35, 17},
{13, 9, 26, 21}};
int num = arr[0][1];//将第一行第二列元素22赋值给num
System.out.println(num);
arr[1][1] = 100;//把100赋值给第二行第二列的元素。
System.out.println(arr[1][1]);
}
二维数组的内存分配
在Java中二维数组本身有一个堆区空间,内部每一个一维数组也有自己独立的堆区空间。二维数组中存储的是每一个一维数组的起始地址。
在C语言中,二维数组所有元素的内存是连续的。
二维数组注意事项
数组下标越界
每一维的下标都不能越界。
空指针异常
二维数组的数组名赋值为null的时候,不能再操作数据。
二维数组内的每个一维数组赋值为null的时候,不能再操作数据。
二维数组的遍历
二维数组的遍历指的是找到数组中每个元素。通常使用循环嵌套来遍历数组元素。
遍历二维数组的通用格式
数据类型[][] 数组名 = new 数据类型[第一维元素个数][第二维元素个数];
for(int i = 0; i < 数组名.length; i++){
for(int j = 0; j < 数组名[i].length; j++){
数组名[i][j] // 数组名[i][j]就是具体的元素。
}
}
二维数组遍历示例
1. 需求:定义一个二维数组{{8, 22, 35, 17}, {13, 9, 26, 21}},遍历数组中的元素。
2. 代码:
public static void main(String[] args) {
int[][] arr = {{8, 22, 35, 17},
{13, 9, 26, 21}};
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();
}
}
二维数组案例
1. 需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70]。
2. 代码:
public static void main(String[] args) {
//需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70]。
//分析:
//1.创建一个3行5列的二维数组
//2.创建Random对象
//3.通过循环为二维数组赋值。
int[][] arr = new int[3][5];
Random random = new Random();
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = random.nextInt(70 - 30 + 1) + 30;
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
3. 需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],求数组中的最大值。
4. 代码:
public static void main(String[] args) {
//需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],求数组中的最大值。
//分析:
//1.创建一个3行5列的二维数组
//2.定义一个变量max保存最大值
//3.创建Random对象
//4.通过循环为二维数组赋值。在赋值的过程中,判断元素和max谁大,如果元素大,把元素赋值给max
int[][] arr = new int[3][5];
int max = 0;
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
arr[i][j] = random.nextInt(70 - 30 + 1) + 30;
System.out.print(arr[i][j] + " ");
if (arr[i][j] > max) {
}
max = arr[i][j];
}
System.out.println();
}
System.out.println("max = " + max);
}
三维数组
上图就是三维数组的一个模型。一维数组是线性的,二维数组是平面,有行和列的概念,三维数组是一个立体,有长宽高的概念。
三维数组的定义
数据类型[] [] [] 数组名 = new 数据类型[第一维元素个数] [第二维元素个数] [第三维元素个数];
示例:
int[] [] [] arr = new int[3] [4] [3];
含义:定义了一个3层4行3列的数组。即一共3层,每层4行,每行3列。
三维数组元素的访问
数组名[下标1] [下标2] [下标3]
示例:
arr[0] [1] [1] = 30;//将第1层,第2行,第2列的值设置为30
int num = arr[0] [1] [1]; //将第1层,第2行,第2列的值赋值给num
三维数组的遍历
数据类型[][][] 数组名 = new 数据类型[第一维元素个数][第二维元素个数][第三维元素个数];
for(int i = 0; i < 数组名.length; i++){
for(int j = 0; j < 数组名[i].length; j++){
for(int k = 0; k < 数组名[i][j].length; k++){
数组名[i][j][k] //数组名[i][j][k]就是被遍历到的数组元素
}
}
}
三维数组示例
1. 需求:创建一个3层3行5列的三维数组,每个元素是[10, 80]之间的随机数,找出数组中的最大值,以及最大值元素的下标。
2. 代码:
public static void main(String[] args) {
//需求:创建一个3层3行5列的三维数组,每个元素是[10, 80]之间的随机数.
//找出数组中的最大值,以及最大值元素的下标。
//分析:
//1.创建一个三维数组
//2.创建Random对象
//3.定义一个变量max保存元素的最大值
//4.通过循环为数组赋值,并求出最大值。
int[][][] arr = new int[3][3][5];
Random random = new Random();
int max = 0;
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
for(int k = 0; k < arr[i][j].length; k++) {
arr[i][j][k] = random.nextInt(80 - 10 + 1) + 10;
System.out.print(arr[i][j][k] + " ");
if(arr[i][j][k] > max) {
max = arr[i][j][k];
}
}
System.out.println();
}
System.out.println();
}
System.out.println("max = " + max);
//找最大值的下标
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
for(int k = 0; k < arr[i][j].length; k++) {
if(arr[i][j][k] == max) {
System.out.println("i = " + i + ",j = " + j + ",k = " + k);
}
}
}
}
}
多维数组
多维数组的定义
数据类型 []...[] 数组名 = new 数据类型[第1维元素个数] ...[第n维元素个数];
多维数组元素的访问
数组名[下标1]..[下标n]
多维数组的遍历----n层循环
数据类型[]...[] 数组名 = new 数据类型[第一维元素个数]...[第n维元素个数];
for(int i = 0; i < 数组名.length; i++){
for(int j = 0; j < 数组名[i].length; j++){
...{
for(int k = 0; k < 数组名[i][j].length; k++){
数组名[i]...[k] //数组名[i]...[k]就是被遍历到的数组元素
}
}
}
}
常用
1. 数组是一个容器,用于存储数据。数组在创建的时候要确定容量,数组内部的元素类型必须相同。
2. 数组的长度:数组名.length
3. 数组可以动态初始化,也可以静态初始化。
4. 数组的遍历,几维数组就用几层循环嵌套来遍历。
5. 数组通常和循环结合使用。
6. 数组元素的访问:数组名[下标] -----几维数组就要有几个下标。