数组的复制、反转、查找、排序
复制
其中最关键的一点是搞清楚为什么数组复制和基本数据类型复制不同,是什么导致了这样的不同?
先来看例子
package com.atguigu.java;
public class ArrayTest3 {
public static void main(String[] args) {
//新建arr数组并输出
int[] arr = new int[]{60,56,78,24,90,63};
System.out.println("arr数组:");
for(int i = 0;i<arr.length;i++){
System.out.print(arr[i] + " ");
}
System.out.println();
//虚假的数组复制
int[] arr1;
arr1 = arr;
//真实的数组的复制
int[] arr2 = new int[arr.length];
for (int i = 0;i < arr.length;i++){
arr2[i] = arr[i];
}
// 修改一下arr里面的值
for (int i = 0; i < arr2.length; i++) {
if (i % 2 == 0) {
arr[i] = i;
}
}
System.out.print("修改后的arr1数组");
for(int i = 0;i<arr.length;i++){
System.out.print(arr1[i] + " ");
}
System.out.println();
System.out.println("----------------");
System.out.print("修改后的arr2数组");
for(int i = 0;i<arr.length;i++){
System.out.print(arr2[i] + " ");
}
System.out.println();
System.out.println("----------------");
}
}
最后输出的结果是:
arr数组:
60 56 78 24 90 63
修改后的arr1数组0 56 2 24 4 63
----------------
修改后的arr2数组60 56 78 24 90 63
----------------
我们会发现通过=
赋值来进行复制的操作让arr1在arr内值变化的同时也跟着变化,相当于一个快捷方式arr1指向了arr数组的真实数据,实际上在内存中也是这样,下面这张图就是相似的情况,两个变量名指向了同一片地址的内容。
到这里你已经理解为什么修改arr1,arr也会跟着变了。因为他们根本就是同一个数组。
那么,我们不妨进一步进行总结,为什么int型、double型、Boolean型这些变量通过=
来复制就没有问题?
答案是:数据类型不同
Java的8种基本数据类型,byte,short,int,Long,flout,double,boolean,char
它们在声明和初始化时,都是存储在栈内存中的,相当于变量内直接就是值,那么,通过=
来进行赋值就理所当然,也很直观。
而引用数据类型,例如String、数组
等 这里的String是一个例外,虽然他也是存储的地址,但是对两个指向同一地址的变量之一进行修改时,会创建新的变量,有待后续研究,以及需要new
关键字来声明的对象,是存放在其他内存中的,所以变量中存储的,只是一个地址值,如果这时候我们通过=
来进行赋值,相当于只对地址进行了复制,而地址相同,指向的内存也当然相同了。相当于对同一对象进行操作,并没有真正创建一个新的数组。
反转
两种方式
public class ArrayTest3 {
public static void main(String[] args) {
//求数组
String[] arr = new String[]{"我","是","恒","星","同","学"};
System.out.println("arr数组:");
for(int i = 0;i<arr.length;i++){
System.out.print(arr[i] + " ");
}
System.out.println();
//数组的反转:
// 方式一:
System.out.println("通过方式一反转:");
for (int i = 0; i < arr.length / 2; i++){
String temp = arr[i];
arr[i] = arr[arr.length - i - 1];
arr[arr.length - i - 1] = temp;
}
for(int i = 0;i<arr.length;i++){
System.out.print(arr[i] + " ");
}
System.out.println();
//方式二
System.out.println("通过方式二反转:");
for (int i = 0,j = arr.length - 1; i < j; i++,j--) {
String temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
for(int i = 0;i<arr.length;i++){
System.out.print(arr[i] + " ");
}
System.out.println();
System.out.println("----------------");
}
}
结果为:
arr数组:
我 是 恒 星 同 学
通过方式一反转:
学 同 星 恒 是 我
通过方式二反转:
我 是 恒 星 同 学
----------------
查找
线性查找
查找刚刚的数组,线性查找只是依次比对每个元素
//线性查找
String dest = "星";
Boolean isFlag = false;
for (int i = 0; i < arr.length; i++) {
if (arr[i].equals(dest)) {
System.out.println("找到了,是索引为" + i + "的元素。");
isFlag = true;
break;
}
}
if (!isFlag) {
System.out.println("没找到。");
}
结果
arr数组:
我 是 恒 星 同 学
找到了,是索引为3的元素。
二分查找
前提:数组中元素有序
int[] arr = new int[]{12,23,45,56,67,78,90};
//二分查找
int dest = 56;
int head = 0;//初始的首索引
int end = arr.length - 1;
Boolean isFlag = false;//找到了吗?
while (head <= end) {//等于的情况也要考虑
int middle = (head + end) / 2;
if (arr[middle] == dest) {
System.out.println("找到了!索引为:" + middle);
isFlag = true;
break;
} else if (arr[middle] > dest){
end = middle - 1;
} else if (arr[middle] < dest){
head = middle + 1;
}
}
if (!isFlag) {
System.out.println("很遗憾,没找到你想要的。");
}
排序
面向工资的话,需要至少掌握冒泡排序和快速排序。
冒泡排序
可以点这里查看冒泡排序动画
//冒泡排序
//这是一个最简单的,不考虑优化的实现,即:每次都把所有数据比对一遍
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;
}
}
}
这里面可以解释一下为什么第二个循环是结束条件是j < arr.length - 1 - i
。
首先第一层循环条件是这个算法总共遍历多少轮,我们来看下面这张图,数组中有8个元素,这是第一轮遍历已经完成的结果,最后一个元素已经是最大。那么下一次我们只需要比对前7个元素,再比对6轮即可(共计7轮),因为比对到最后一轮时,第二个元素的位置已经确定,只剩下最后一个元素,他的位置不会再变了。所以第一个for循环结束条件是i < arr.length - 1
。
其次,第二层是从第一个元素对比到当前无序的最后一个元素,拿上面这张图的例子来说,现在第二轮是比对从1到7这7个元素,arr.length - 1
是当前数组的长度,显然还不够,还要再减去已经排好顺序的元素个数i
,就变成了j < arr.length - 1 - i
。
优化
如果在某一步执行完时所有元素已经全部有序,那么下一步便不会再有数据交换发生 。抓住这一特点,我们可以让冒泡排序在检测到当前没有发生元素交换时主动结束。
//冒泡排序
for (int i = 0; i < arr.length - 1; i++) {
Boolean swap = true;
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;
}else {
swap = false;
}
if (!swap) {
break;
}
}
}
快速排序
日后再说。