Java(九)数组(3)冒泡排序、插入排序以及数组元素查找

目录

 

六、数组的排序

七、数组元素查找


六、数组的排序

(1)冒泡排序

冒泡排序法是最基本的排序法之一,冒泡排序法的运行机制是通过循环遍历元素并调整相邻元素顺序来实现的一种简单排序方法。

以数组 {21, 99, 3, 1024, 16}升序排列为例演示冒泡排序的原理:

1、

冒泡排序法每一次排序目的是将数值较大(针对于升序排序)或较小(针对于降序排序)的元素移动到数组的尾部。

以升序为例:

第一次循环:将元素21与元素99进行比较,由于21 < 99,所以不用交换元素;

第二次循环:将元素99与元素3进行比较,由于99 > 3,所以需要交换元素(即993的位置互换,数组的序列被调整为 {21, 3, 99, 1024, 16});

第三次循环:将元素99与元素1024进行比较,由于99 < 1024,所以也不用交换元素;

第四次循环:将元素1024与元素16进行比较,由于1024 < 16,所以需要交换元素(即102416的位置互换)。

经过第一次遍历将最大的元素1024调整到了数组的尾部,数组序列变为 {21, 3, 99, 16, 1024}

2、

冒泡排序法的第二次排序与第一次原理一致,只不过第二次排序不再关系数组尾部元素,因为经过前一次排序后,数组尾部元素已经存储了数组中数值最大的元素,所以第二次排序的目的是将数组中数值第二大的元素存储到数组的倒数第二个位置(即此时只关心数组前四个元素 {21, 3, 99, 16}的顺序)。

第一次循环:将元素21与元素3进行比较,由于21 > 3,所以需要交换元素(即213位置互换,数组的前四位序列被调整为 {3, 21, 99, 16});

第二次循环:将元素21与元素99进行比较,由于21 < 99,所以不用交换元素;

第三次循环:将元素99与元素16进行比较,由于99 > 16,所以需要交换元素(即9916的位置互换);

第四次循环:将元素99与元素1024进行比较,由于99< 1024,所以不用交换元素。

经过第二次排序数组序列变为 {3, 21, 16, 99, 1024}

3、

冒泡排序法的第三次排序与第一次原理一致,只不过第三次次排序不再关系数组倒数第二个位置元素,因为经过前一次排序后,数组倒数第二个位置元素已经存储了数组中数值第二大的元素,所以第三次排序的目的是将数组中数值第三大的元素存储到数组的倒数第三个位置(即此时只关心数组前四个元素 {3, 21, 16}的顺序)。

第一次循环:将元素3与元素21进行比较,由于3 < 21,所以不用交换元素;

第二次循环:将元素21与元素16进行比较,由于21 > 16,所以需要交换元素(即2116位置互换,数组的前三位序列被调整为 {3, 16, 21});

第三次循环:将元素21与元素99进行比较,由于12 < 99,所以不需要交换元素;

第四次循环:将元素99与元素1024进行比较,由于99< 1024,所以不用交换元素。

经过第三次排序数组序列变为 {3,16, 21, 99, 1024}

4、

冒泡排序法的第四次排序与第一次原理一致,只不过第四次次排序不再关系数组倒数第三个位置元素,因为经过前一次排序后,数组倒数第三个位置元素已经存储了数组中数值第三大的元素,所以第四次排序的目的是将数组中数值第四大的元素存储到数组的倒数第四个位置(即此时只关心数组前四个元素 {3, 16}的顺序)。

第一次循环:将元素3与元素16进行比较,由于3 < 16,所以不用交换元素;

第二次循环:将元素16与元素21进行比较,由于16 < 21,所以不用交换元素;

第三次循环:将元素21与元素99进行比较,由于12 < 99,所以不需要交换元素;

第四次循环:将元素99与元素1024进行比较,由于99< 1024,所以不用交换元素。

经过第四次排序数组序列变为 {3,16, 21, 99, 1024}。由于数组一共包含五个元素,则排序完成。

public class ArraySort{
	public static void main(String [] args){
		int [] array={21, 99, 3, 1024, 16};//升序排列
		for(int loopTime=1;loopTime<array.length;loopTime++){//只是控制内部for循环的次数
			for(int i=0;i<array.length-1;i++){//该for循环每循环一次就会将较大的数据放在适当的位置,比如loopTime=1;则将最大数据放在最后;loopTime=2;则将第二大数据放在倒数第二个元素位置;
				int currentData = array[i];//当前遍历出来的数据
				int nextData = array[i+1];//当前数据下标对应的下一个元素的数据
				if(currentData>nextData){//如果当前元素大于其后面的元素,则意味着需要调换两个元素之间的位置
					array[i] = nextData;
					array[i+1]=currentData;
				}
			}
		}

		for(int data:array){
			System.out.print(data+" ");
		}
	}
}

以下代码和上一个代码不同的地方:array.length-loopTime:从提高代码的性能角度出发,减少该循环“多余”的循环次数; 

public class ArraySort{
	public static void main(String [] args){
		int [] array={21, 99, 3, 1024, 16};//升序排列
		for(int loopTime=1;loopTime<array.length;loopTime++){//只是控制内部for循环的次数
			for(int i=0;i<array.length-loopTime;i++){//该for循环每循环一次就会将较大的数据放在适当的位置,比如loopTime=1;则将最大数据放在最后;loopTime=2;则将第二大数据放在倒数第二个元素位置;array.length-loopTime:从提高代码的性能角度出发,减少该循环“多余”的循环次数
				int currentData = array[i];//当前遍历出来的数据
				int nextData = array[i+1];//当前数据下标对应的下一个元素的数据
				if(currentData>nextData){//如果当前元素大于其后面的元素,则意味着需要调换两个元素之间的位置
					array[i] = nextData;
					array[i+1]=currentData;
				}
			}
		}

		for(int data:array){
			System.out.print(data+" ");
		}
	}
}

 •冒泡排序的实质是相邻两个元素比较,然后按照升序或降序调换位置。

 (2)插入排序

每循环一次都将一个待排序的元素所对应的数据按其顺序大小插入到前面已经排序的序列的合适位置,直到全部插入排序完为止,其难点在于如何在前面已经排好序的序列中找到合适的插入位置。该排序方法有很多,比如直接插入排序、二分插入排序、希尔排序等等。

先看如何解决这个问题:已知数组{1, 2, 4, 5, 3},将3插入到适当位置,使之成为一个升序排列的数组,即{1, 2, 3, 4, 5}

public class SortArray {
	
	/**
	 * 已知数组{1, 2, 4, 5, 3},将3插入到适当位置,使之成为一个升序排列的数组,即{1, 2, 3, 4, 5}
	 */
	public static void main(String[] args) {
		int[] array = new int[]{1, 2, 4, 5, 3};
		int i=4;//待插入元素数据3所在位置
		int willSortData = array[i];//将待插入元素数据3保存在临时变量willSortData中
		int j = 0;
		for (; j < i; j++) {
			if(willSortData<=array[j]){//找到应该插入3的索引位置
				break;//找到插入位置后结束该循环
			}
		}
		
		//System.out.println(j);//输出2,即数据3应该插入到数据4的位置
		
		int k=i;//待插入元素数据所在位置
		for (; k >j; k--) {//从待插入元素数据所在位置(即第5个元素)将数组元素后移一个元素位,直到待插入数据该插入位置(不包含)结束
			array[k]=array[k-1];
		}

		array[j]=willSortData;//将待插入数据插入到该插入的位置,即在排序位置插入数据待排序数据
		
		for (int data : array) {
			System.out.print(data+" ");
		}
	}
}
public class ArraySort{

	public static void main(String [] args){
		int [] array={1,2,6,7,2,9,12,2};//升序排列
		for(int i=1;i<array.length;i++){//i为待排序数据的下标,由于将第一个元素是有序的,所以i从1开始;i<array:这样才能遍历完后续数组,进而实现全部排序;
			int willSortData=array[i];//将待排序数据保存到变量willSortData中
			int j=0;
			/*
			 *查找待插入数据“应该”插入的下标位置
			 */
			for(;j<i;j++){//j<i:和待排序数据前面(i)的所有元素进行比较,以找到“应该”插入的下标位置。说明:不能这样写j<=i,因为无需自己和自己比对
				if(willSortData<array[j]){//如果条件成立意味着待插入数据小于其前面的某个元素值
					break;//当if条件成立时就找到了该待插入数据“应该”插入的下标位置,所以这时必须终止循环
				}
			}//for循环执行结束意味着找到了待插入数据“应该”插入的下标位置

			/*
			 *下面循环用于元素后置
			 */
			for(int k=i;k>j;k--){//int k=i:待插入数据所在位置就是元素后移开始的下标位置;k>j:待插入数据“应该”插入位置(j)就是元素后移结束位置
				array[k]=array[k-1];//元素后置
			}
			
			/*
			 *下面代码用于将待插入数据插入到“应该”插入的下标位置
			 */
			array[j]=willSortData;
		}//该循环体每循环完一次就代表着本次待插入数据已经和前面元素是有序的了

		for(int data:array){
			System.out.print(data+" ");
		}
	}
}

以下代码有部分内容与上一个代码不同,具体请看代码与注释:

public class ArraySort{

	public static void main(String [] args){
		int [] array={1,2,6,7,2,9,12,2};//升序排列
		for(int i=1;i<array.length;i++){//i为待排序数据的下标,由于将第一个元素是有序的,所以i从1开始;i<array:这样才能遍历完后续数组,进而实现全部排序;
			int willSortData=array[i];//将待排序数据保存到变量willSortData中
			int j=0;
			/*
			 *查找待插入数据“应该”插入的下标位置
			 */
			for(;j<i;j++){//j<i:和待排序数据前面(i)的所有元素进行比较,以找到“应该”插入的下标位置。说明:不能这样写j<=i,因为无需自己和自己比对
				if(willSortData<array[j]){//如果条件成立意味着待插入数据小于其前面的某个元素值
					break;//当if条件成立时就找到了该待插入数据“应该”插入的下标位置,所以这时必须终止循环
				}
			}//for循环执行结束意味着找到了待插入数据“应该”插入的下标位置
			
			if(i==j){//i与j相等意味着不用排序,下面代码也不用执行
				continue;//停止不用排序这次循环,进入下次循环
			}
			
			/*
			 *下面循环用于元素后置
			 */
			for(int k=i;k>j;k--){//int k=i:待插入数据所在位置就是元素后移开始的下标位置;k>j:待插入数据“应该”插入位置(j)就是元素后移结束位置
				array[k]=array[k-1];//元素后置
			}
			
			/*
			 *下面代码用于将待插入数据插入到“应该”插入的下标位置
			 */
			array[j]=willSortData;
		}//该循环体每循环完一次就代表着本次待插入数据已经和前面元素是有序的了

		for(int data:array){
			System.out.print(data+" ");
		}
	}
}

提高了程序的性能。

插入排序的实质:将数组分为有序区和无序区,定义一个标记无序区第一个元素的定位变量,将该元素与前面的有序区内元素遍历比较,找到该元素应该插入位置,然后将插入位置到插入元素所在位置之间的元素后移一位,最后再将待插入元素插入到应插入的位置,有序区扩增一位,无序区减少一位,定位变量再次后移,锁定后面无序区第一位元素位置。

 

当然,只看代码也许没办法看懂,需要多多练习。

七、数组元素查找

二分法查找:搜索数据与有序数组(比如升序)中间元素比较以确定在中间元素左边还是右边,如果在右边,则调整最小搜索索引值,然后进入下次循环;如果在左边,则调整最大搜索索引值,然后进入下次循环;如果相等则当前位置就是查找数据所在位置,停止循环;

import java.util.Arrays;

public class Test {

	public static int search(int[] array, int data) {
		Arrays.sort(array);// 将数组升序排列
		
		int low = 0;
		int high = array.length - 1;
		while (low <= high) {
			int middle = (low + high) / 2;
			// 搜索数据与中间元素比较确定在中间元素左边还是右边,进而不断缩小查找范围
			if (data > array[middle]) {//右边
				low = middle + 1;
			} else if (data < array[middle]) {//左边
				high = middle - 1;
			} else {
				return middle;
			}
		}
		return -1;
	}

	public static void main(String[] args) {
		int[] numbers = {5, 1, 7, 3, 2};
		int index = search(numbers, 5);
		if (index != -1) {
			System.out.println("数组中包含该数据");
		} else {
			System.out.println("数组中不包含该数据");
		}
	}
}

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值