准备工作
这里设计一个类,包含了对数组的基本操作,如使用随机数初始化数组元素,输出数组元素等等。在今后的案例中,我们会根据需要,逐步向这个类中添加方法,完成更多的功能。
ArrayOP.java代码如下:
import java.util.Random;
/*
数组的基本操作
*/
public class ArrayOP {
//init方法用于使用随机数初始化一个数组,bound表示元素的最大值
public void init(int[] a,int bound){
Random r=new Random();
//使用随机值为数组元素赋值,元素值为[0,bound)
for (int i = 0; i < a.length; i++) {
a[i]=r.nextInt(bound);
}
}
//printArray方法用于输出数组中的元素,五个一行
public void printArray(int[] a){
for (int i = 0; i < a.length; i++) {
//依次输出每一个元素,用制表符隔开
System.out.print("数组第"+i+"号元素是:"+a[i]+"\t");
if((i+1)%5==0){
//每输出5个元素,输出一个换行符
System.out.println();
}
}
System.out.println();
}
//printArrayEach是采用了for each循环的数组输出方法
public void printArrayEach(int[] a) {
int count=0;
for (int i : a) {
System.out.print("数组第" + count + "号元素是:" + i + "\t");
if ((count + 1) % 5 == 0) {
// 每输出5个元素,输出一个换行符
System.out.println();
}
count++;
}
}
}
在ArrayTest01.java中调用ArrayOP.java中的方法初始化一个数组并输出。
public class ArrayTest01 {
public static void main(String[] args) {
int[] a=new int[100];
ArrayOP ao=new ArrayOP();
//初始化数组a,数组元素值限定为1000以内
ao.init(a,1000);
//输出元素值
ao.printArray(a);
}
}
03
冒泡法排序
冒泡法是一种常见的排序算法,其基本思路是从头至尾,将相邻的两个元素比较大小,如果前面的元素大,就交换两个元素,将大的元素放到后面。这样,经过一轮比较,就可以将最大的元素放到数组的最后。如此经过(数组长度-1)轮比较后,就可以把第一大、第二大……的元素放到数组最后、倒数第二……的位置上,从而完成整个数组的排序了。之所以是(数组长度-1)轮比较,因为这么多轮比较后,只剩一个元素还没有确定位置,但其他元素的位置都已经确定,所以这最后一个元素的位置也就不得不确定了。
我们向ArrayOP.java中添加代码:
//bubbleSort方法使用冒泡法为数组排序
public void bubbleSort(int[] a){
//临时变量temp
int temp;
for(int i=0;i<a.length-1;i++){
for(int j=0;j<a.length-i-1;j++){
//每一轮都会确定一个元素的位置,所以只需要在剩下的元素中比较就可以了
//因此循环条件是j<a.length-i-1
if(a[j]>a[j+1]){
//如果前面的元素比后面的大,交换位置
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
}
为了更清楚地显示冒泡法的执行过程,我们编写ArrayTest02.java程序,代码如下:
public class ArrayTest02 {
public static void main(String[] args) {
int[] a=new int[5];
ArrayOP ao=new ArrayOP();
//使用100以内的整数初始化数组元素
ao.init(a,100);
System.out.println("数组的元素值为:");
ao.printArray(a);
System.out.println("---------------------------------");
//排序
ao.bubbleSort(a);
ao.printArray(a);
System.out.println("---------------------------------");
/*这部分程序展示了排序的过程
//临时变量temp
int temp;
for(int i=0;i<a.length-1;i++){
for(int j=0;j<a.length-i-1;j++){
if(a[j]>a[j+1]){
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
System.out.println("这是第"+i+"轮中的第"+j+"次操作结果:");
ao.printArray(a);
}
System.out.println("---------------------------------");
}
*/
}
}
运行结果为:
数组的元素值为:
数组第0号元素是:79 数组第1号元素是:27 数组第2号元素是:49 数组第3号元素是:86 数组第4号元素是:78
---------------------------------
这是第0轮中的第0次操作结果:
数组第0号元素是:27 数组第1号元素是:79 数组第2号元素是:49 数组第3号元素是:86 数组第4号元素是:78
这是第0轮中的第1次操作结果:
数组第0号元素是:27 数组第1号元素是:49 数组第2号元素是:79 数组第3号元素是:86 数组第4号元素是:78
这是第0轮中的第2次操作结果:
数组第0号元素是:27 数组第1号元素是:49 数组第2号元素是:79 数组第3号元素是:86 数组第4号元素是:78
这是第0轮中的第3次操作结果:
数组第0号元素是:27 数组第1号元素是:49 数组第2号元素是:79 数组第3号元素是:78 数组第4号元素是:86
---------------------------------
这是第1轮中的第0次操作结果:
数组第0号元素是:27 数组第1号元素是:49 数组第2号元素是:79 数组第3号元素是:78 数组第4号元素是:86
这是第1轮中的第1次操作结果:
数组第0号元素是:27 数组第1号元素是:49 数组第2号元素是:79 数组第3号元素是:78 数组第4号元素是:86
这是第1轮中的第2次操作结果:
数组第0号元素是:27 数组第1号元素是:49 数组第2号元素是:78 数组第3号元素是:79 数组第4号元素是:86
---------------------------------
这是第2轮中的第0次操作结果:
数组第0号元素是:27 数组第1号元素是:49 数组第2号元素是:78 数组第3号元素是:79 数组第4号元素是:86
这是第2轮中的第1次操作结果:
数组第0号元素是:27 数组第1号元素是:49 数组第2号元素是:78 数组第3号元素是:79 数组第4号元素是:86
---------------------------------
这是第3轮中的第0次操作结果:
数组第0号元素是:27 数组第1号元素是:49 数组第2号元素是:78 数组第3号元素是:79 数组第4号元素是:86
---------------------------------
快速排序
快速排序的基本思路是,在数组中找一个元素为基准值(一般是数组中间的元素或第一个元素),然后把其他元素中比基准值大元素放到其右侧,比基准值小的元素放到其左侧,然后对左右两侧的子数组进行相同的操作,直到完成排序为止。在ArrayOP.java中添加quickSort方法:
//快速排序法
public void quickSort(int[] a,int leftIndex,int rightIndex) {
//保存排序的范围
int left=leftIndex;
int right=rightIndex;
//start用于保存排序时的基准值
int start;
//临时变量,用于交换两个元素
int temp;
if(rightIndex>leftIndex) {
//将数组中间的元素设置为基准值,使用其他元素也能起到相同的效果
start=a[(leftIndex+rightIndex)/2];
while(left<=right) {
//在左半边找到比基准值大的元素
while((left<rightIndex)&&(a[left]<start)) {
left++;
}
//在右半边找到比基准值小的元素
while((right>leftIndex) && (a[right]>start)) {
right--;
}
//将左边比基准值大的元素和右边比基准值小的元素交换位置
if(left<=right) {
temp=a[left];
a[left]=a[right];
a[right]=temp;
left++;
right--;
}
}
//对基准值两边的部分,再次执行上面的排序
if(leftIndex<right) {
quickSort(a, leftIndex, right);
}
if(left<rightIndex) {
quickSort(a, left, rightIndex);
}
}
}
测试时可以将ArrayTest02.java程序中的ao.bubbleSort(a);
替换为ao.quickSort(a);
逆序排序
之前讲过的方法是从小到大的排序,如果我们需要从大到小排序(逆序),怎么办呢?修改代码肯定是一种方法,但如果不想过多修改代码,那么可以先按照从小到大排序,然后交换首尾元素值,把数组“翻转过来”就可以了。方法如下:
//将数组元素头尾互换,翻转过来
public void reverse(int[] a) {
int temp;
for(int i=0;i<=(a.length-1)/2;i++) {
temp=a[i];
a[i]=a[a.length-1-i];
a[a.length-1-i]=temp;
}
}
测试时可以在ArrayTest02.java程序执行排序后,然后翻转数组,看输出结果即可。
03
顺序查找
最简单的查找方法就是顺序朝招,从第一个元素开始,依次比较数组元素和查找对象,如果某个元素和对象值相等,说明查找到了;如果尝试了所有的元素没有找到与查找对象相等的元素,则表示没有找到。在ArrayOP.java中添加search方法:
//顺序查找
public int search(int[] a,int key){
int index=-1;
for(int i=0;i<a.length;i++){
if(a[i]==key){
index=i;
break;
}
}
return index;
}
编写ArrayTest03.java程序测试这个方法:
public class ArrayTest03 {
public static void main(String[] args) {
ArrayOP ao=new ArrayOP();
//创建一个有10个元素的数组a,并使用不大于100的随机数初始化
int[] a=new int[10];
ao.init(a, 10);
ao.printArray(a);
//在数组a中查找数值5
int index=ao.search(a, 5);
if(index==-1) {
System.out.println(5+"不在数组中");
}else {
System.out.println(5+"在数组中,位置索引值为:"+index);
}
}
}
二分法查找
上面的查找算法简单有效,但如果要查找的数据位于数组的结尾处,或者不存在于数组中,就需要花费较长的时间。为了缩短查找时间,我们可以采用二分法查找。二分法查找的基本思路是:先将数组排序,然后对比查找对象和中间那个元素的值,如果两者相等,则找到;如果不相等,而且中间元素比查找对象大,则到数组的左半部分继续按照前述方法查找;如果不相等,而且中间元素比查找对象小,则到数组的右半部分继续按照前述方法查找。
还记得猜数字游戏吗?我们可以使用二分法查找的思想来玩这个游戏:如果数字处于0到100之间,我们第一次就猜50(0到100的中间值),如果游戏提示我们猜小了,就猜75(50到100的中间值),如果游戏提示我们猜大了,就猜63(50到75的中间值)……由此可以提高猜对的概率。
二分法查找的思路是每次排除不正确的一半数据,因此可以大大提高查找速率。
在ArrayOP.java中添加binarySearch方法:
//二分法查找,leftIndex和rightIndex为查找的左右边界
public int binarySearch(int[] a,int v,int leftIndex,int rightIndex) {
//去数组中间元素的索引值
int middle=(leftIndex+rightIndex)/2;
//左边界不能在右边界的右边
if(leftIndex<rightIndex) {
if(a[middle]==v) {
//如果中间这个元素等于v表示找到了,返回middle值
return middle;
}else if(a[middle]>v) {
//如果中间元素比v大,则到数组左半边查找
return binarySearch(a, v, leftIndex, middle-1);
}else {
//如果中间元素比v小,则到数组右半边查找
return binarySearch(a, v, middle+1, rightIndex);
}
}
//如果前面的程序没有结果,那么返回-1,表示没有找到
return -1;
}
我们改动一下ArrayTest03.java程序,让第一种方法是第二种方法的验证标准。
public class ArrayTest03 {
public static void main(String[] args) {
ArrayOP ao=new ArrayOP();
//创建一个有10个元素的数组a,并使用不大于100的随机数初始化
int[] a=new int[10];
ao.init(a, 10);
ao.printArray(a);
//在数组a中查找数值50
int index=ao.search(a, 5);
if(index==-1) {
System.out.println(5+"不在数组中");
}else {
System.out.println(5+"在数组中,位置索引值为:"+index);
}
//使用二分法查找
System.out.println("------二分法查找结果------");
//先从小到大排序
ao.bubbleSort(a);
ao.printArray(a);
//开始二分法查找
int index2=ao.binarySearch(a, 5, 0, a.length-1);
//检查查找结果
if(index2==-1) {
System.out.println(5+"不在数组中");
}else {
System.out.println(5+"在数组中,位置索引值为:"+index2);
}
//对比两次查找的结果,相同输出true,不同输出false
System.out.println((index>-1)==(index2>-1));
}
}
03
最大值和最小值
在求一个数组最大值和最小值时,可以首先假设任意一个元素(一般是第一个元素)为最大值(最小值),然后和其他元素依次比较,如果发现更大(更小)的值则假设这个新发现的元素为最大值(最小值)。将所有元素都检测一遍,就能找到最大值和最小值了。
代码如下:
// 找数组的最大值
public int maxValue(int[] a) {
int max = a[0];
for (int i = 1; i < a.length; i++) {
if (max < a[i]) {
max = a[i];
}
}
return max;
}
// 找数组的最小值
public int minValue(int[] a) {
int min = a[0];
for (int i = 1; i < a.length; i++) {
if (min > a[i]) {
min = a[i];
}
}
return min;
}
我们可以编写程序Array04.java进行测试,代码如下:
public class Array04 {
public static void main(String[] args) {
ArrayOP ao=new ArrayOP();
//创建一个有10个元素的数组a,并使用不大于100的随机数初始化
int[] a=new int[10];
ao.init(a, 100);
//排序
ao.quickSort(a, 0, a.length-1);
//输出排序后的数组,第一个元素就是最小值,最后一个元素就是最大值
ao.printArray(a);
System.out.println("数组中的最大值为:"+ao.maxValue(a));
System.out.println("数组中的最小值为:"+ao.minValue(a));
}
}
Java提供的常用数组工具
- 复制数组:
System.arrayCopy(Object src, int srcPos, Object dest, int desPos, int length)
,参数的含义是:源数组, 源数组开始复制的位置, 目标数组, 目标数组开始存放的位置, 复制元素数量 - 快速排序:
Arrays.sort()
,参数为待排序的数组名 - 二分法查找:
Arrays.binarySearch()
,有两个参数,第一个为待查找的数组,第二个为要查找的值,如果找到,返回该元素的索引值;如果找不到,返回一个负数。
下面我们使用这些方法来完成复制数组、排序和查找等数组操作:
import java.util.Arrays;
public class ArrayTest04 {
public static void main(String[] args) {
ArrayOP ao=new ArrayOP();
//创建一个有10个元素的数组a,并使用不大于10的随机数初始化
int[] a=new int[10];
ao.init(a, 10);
System.out.println("----------现在输出数组a的内容----------");
ao.printArray(a);
//复制数组中后8个元素
int[] b=new int[8];
System.arraycopy(a, 2, b, 0, 8);
System.out.println("----------现在输出数组b的内容----------");
ao.printArray(b);
//排序
System.out.println("----------现在输出数组a的内容----------");
Arrays.sort(a);
ao.printArray(a);
//查找5是否在数组a中
System.out.println((Arrays.binarySearch(a, 5)>=0)?("5在数组a中,索引值为"+Arrays.binarySearch(a, 5)):"5不在数组a中");
}
}
03