最新Java基础系列课程--Day04-数组(一)https://developer.aliyun.com/article/1423490
我们重点关注这一段代码
刚执行完int[] arr1 = {11,22,33};
时,内存原理如下
当执行完int[] arr2 = arr1;
后,内存原理如下
当执行到arr2[1]=99;时
,内存原理如下
总结一下:
- 两个变量指向同一个数组时,两个变量记录的是同一个地址值。
- 当一个变量修改数组中的元素时,另一个变量去访问数组中的元素,元素已经被修改过了。
到这里有关数组的基本操作,和内存原理我们就全部学习完了。
四、数组专项练习
接下来我们做一些专项练习题,把数组的常见操作练习一下。在学习这个案例时,重点掌握数组求最值的思路,代码只是用来表达你的思路的。
4.1 数组求最值
需求:定义一个int类型数组,求数组中元素的最大值,并打印最大值
我们先看一下选美比赛,是怎么选出颜值最高的人的。然后再以此思路,来写代码找出数组中元素的最大值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sroSwLCj-1689818073800)(assets/1661441712915.png)\
数组求最大值思路: 1)先找出数组中0索引的元素,假设为最大值,用max表示【擂主】 2)遍历后面的每一个元素和max比较,把较大的元素值重新赋值给max(擂主换人) 3)最后max就是所有元素的最大值(最后站在台上的擂主)
public class Test1 { public static void main(String[] args) { // 1、把颜值数据拿到程序中来,用数组装起来 int[] faceScores = {15, 9000, 10000, 20000, 9500, -5}; // 2、定义一个变量用于最终记住最大值。 int max = faceScores[0]; // 3、从数组的第二个位置开始遍历。 for (int i = 1; i < faceScores.length; i++) { // i = 1 2 3 4 5 // 判断一下当前遍历的这个数据,是否大于最大值变量max存储的数据, //如果大于,当前遍历的数据需要赋值给max if(faceScores[i] > max ){ max = faceScores[i]; } } System.out.println("最高颜值是:" + max); } }
总结一下:
通过这个案例,我们主要掌握求最值的思路,以后不管遇到求最大值还是最小值,编程思路都是一样的,不同的可能是数据不同。
4.2 数组元素反转
需求:某个数组有5个数据:10,20,30,40,50,请将这个数组中的数据进行反转。 [10, 20, 30, 40, 50] 反转后 [50, 40, 30, 20, 10]
数组元素反转的核心,其实是数组中两个数据的交换。我们可以认为两个数据分别存储在两个水杯中。想要交换两个水杯中的东西,我们得借助第三个水杯,如下图所示
数组中元素交换,就是用的借用第三方变量的思想。 我们把数组中的每一个元素当做一个水杯,然后索引控制哪两个元素互换位置。
怎么样,才能达到元素反转的效果呢?我们只需将第一个和最后一个元素互换、第二个和倒数第二个互换、依次内推… 如下图所示
怎么样写代码,才能达到上面的效果呢?我们继续分析
1.每次交换,需要有左右两边的两个索引,我们可以用i和j表示 刚开始i=0,j=数组长度-1; 2.每次让i和j索引位置的两个元素互换位置 arr[i]和arr[j]互换位置 3.每次还完位置之后,让i往右移动一位,让j往前移动一位
具体代码如下
public class Test2 { public static void main(String[] args) { // 目标:完成数组反转。 // 1、准备一个数组 int[] arr = {10, 20, 30, 40, 50}; // 2、定义一个循环,设计2个变量,一个在前,一个在后 for (int i = 0, j = arr.length - 1; i < j; i++, j--) { // arr[i] arr[j] // 交换 // 1、定义一个临时变量记住后一个位置处的值 int temp = arr[j]; // 2、把前一个位置处的值赋值给后一个位置了 arr[j] = arr[i]; // 3、把临时变量中记住的后一个位置处的值赋值给前一个位置处 arr[i] = temp; } // 3、遍历数组中的每个数据,看是否反转成功了 for (int i = 0; i < arr.length; i++) { System.out.print(arr[i] + " "); } } }
总结一下:
通过上面的案例,需要我们掌握元素互换位置的编程思路;以后遇到数据互换问题,都这样做。
五、数据排序的多种算法
5.1 冒泡排序
冒泡排序是一种简单的交换排序算法,以升序排序为例,其核心思想是:
1、从第一个元素开始,比较相邻的两个元素。如果第一个比第二个大,则进行交换。
2、轮到下一组相邻元素,执行同样的比较操作,再找下一组,直到没有相邻元素可比较为止,此时最后的元素应是最大的数。
3、除了每次排序得到的最后一个元素,对剩余元素重复以上步骤,直到没有任何一对元素需要比较为止。
package com.dts; //冒泡排序示例 public class BubbleSortDemo { public static void main(String[] args) { int[] arr = {2,5,1,9,3,6,4}; BubbleSortDemo demo = new BubbleSortDemo(); demo.bubbleSortOpt(arr); for(int i=0;i<arr.length;i++){ System.out.println(arr[i]); } } //debug 断点演示 public void bubbleSortOpt(int[] arr) { int temp = 0; //循环数组 外部循环一次,内部循环一遍 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]) { temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } }
5.2 快速排序
快速排序的思想很简单,就是先把待排序的数组拆成左右两个区间,左边都比中间的基准数小,右边都比基准数大。接着左右两边各自再做同样的操作,完成后再拆分再继续,一直到各区间只有一个数为止。
举个例子,现在我要排序 4、9、5、1、2、6 这个数组。一般取首位的 4 为基准数,第一次排序的结果是:
2、1、4、5、9、6
可能有人觉得奇怪,2 和 1 交换下位置也能满足条件,为什么 2 在首位?这其实由实际的代码实现来决定,并不影响之后的操作。以 4 为分界点,对 2、1、4 和 5、9、6 各自排序,得到:
1、2、4、5、9、6
不用管左边的 1、2、4 了,将 5、9、6 拆成 5 和 9、6,再排序,至此结果为:
1、2、4、5、6、9
为什么把快排划到交换排序的范畴呢?因为元素的移动也是靠交换位置来实现的。算法的实现需要用到递归(拆分区间之后再对每个区间作同样的操作)
package com.dts; //快排示例 public class QuickStartDemo { public static void main(String[] args) { int[] arr = {2,5,1,9,3,6,4}; QuickStartDemo demo = new QuickStartDemo(); demo.quickSort(arr,0,arr.length-1); for(int i=0;i<arr.length;i++){ System.out.println(arr[i]); } } public void quickSort(int[] arr, int start, int end) { if(start < end) { // 把数组中的首位数字作为基准数 int stard = arr[start]; // 记录需要排序的下标 int low = start; int high = end; // 循环找到比基准数大的数和比基准数小的数 while(low < high) { // 右边的数字比基准数大 while(low < high && arr[high] >= stard) { high--; } // 使用右边的数替换左边的数 arr[low] = arr[high]; // 左边的数字比基准数小 while(low < high && arr[low] <= stard) { low++; } // 使用左边的数替换右边的数 arr[high] = arr[low]; } // 把标准值赋给下标重合的位置 arr[low] = stard; // 处理所有小的数字 quickSort(arr, start, low); // 处理所有大的数字 quickSort(arr, low + 1, end); } } }