冒泡排序及改进方法

本文介绍了冒泡排序的基础原理及其三次改进方法。第一次改进通过设置标记来避免不必要的比较,第二次改进通过记录交换位置减少循环次数,第三次改进同时寻找最大值和最小值,提升排序效率。测试表明,第三次改进后的冒泡排序循环次数显著降低。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础冒泡排序

元素两两相比较,将最大的元素向后排。
冒泡排序外层循环控制循环次数,
内层循环控制每次循环的比较次数

	public static void bubbleSort(int[] arr) {
		for (int i = arr.length - 1; i > 0; i--) {
			for (int j = 0; j < i; j++) {
				if (arr[j] > arr[j + 1]) {
					arr[j] = arr[j] + arr[j + 1];
					arr[j + 1] = arr[j] - arr[j + 1];
					arr[j] = arr[j] - arr[j + 1];
				}
				System.out.print("0");
			}
		}
	}

冒泡排序第一次改进

数组{0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
按照上面未改进的排序方式,在后面元素已经排序有序后,接下来的排序,即前面的数字{0,1,2}已经不需要排序,就是说这三趟排序是多余的,什么也没做。
因此我们在交换的地方增加一个标记,若是那一趟排序并没有交换元素,则说明数组元素已经有序,不用再继续下去。

	public static void bubbleSortOptimize1(int[] arr) {
		int flag;
		for (int i = arr.length - 1; i > 0; i--) {
			flag = 0;//标记flag
			for (int j = 0; j < i; j++) {
				
				if (arr[j] > arr[j + 1]) {
					arr[j] = arr[j] + arr[j + 1];
					arr[j + 1] = arr[j] - arr[j + 1];
					arr[j] = arr[j] - arr[j + 1];
					flag = 1;
				}
				System.out.print("1");
			}
			if (flag == 0)
				return;
		}
	}

冒泡排序第二次改进

数组{0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
进行了第一次改进之后,其循环次数已经减少。但是我们发现后排元素{99,100,101,102}也是基本有序的,因此,后排元素的循环判断也是不必要的。
记录下最后一次交换的位置,将循环停止条件设置到此位置结束
设置一个索引值,在数组元素进行交换时,将这个交换的位置用索引值记录下来。一直到循环结束,这个索引值就是最后一次进行交换的位置。
将外层循环的停止条件设置为小于此索引值(最后一次进行交换的位置)继续循环。

	public static void bubbleSortOptimize2(int[] arr) {
		int flag;
		int index;
		for (int i = arr.length - 1; i > 0; i--) {
			flag = 0;
			index = i;
			for (int j = 0; j < i; j++) {
				if (arr[j] > arr[j + 1]) {
					arr[j] = arr[j] + arr[j + 1];
					arr[j + 1] = arr[j] - arr[j + 1];
					arr[j] = arr[j] - arr[j + 1];
					flag = 1;
					index = j + 1;
				}
				System.out.print("2");
			}
			if (flag == 0)
				return;
			i = index;
		}
	}

冒泡排序第三次改进

经过前面两次优化,冒泡排序的效率已经大大提高。
第三次改进思想:每次循环比较寻找一个最大值,并且寻找一个最小值。将最大值置于最后,最小值置于最前。
数组{0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};

	public static void bubbleSortOptimize3(int[] arr) {
		int index;
		int flag;
		int n = 0;
		for (int i = arr.length - 1; i > 0; i--) {
			flag = 0;
			index = i;
			for (int j = n; j < i; j++) {
				if (arr[j] > arr[j + 1]) {
					arr[j] = arr[j] + arr[j + 1];
					arr[j + 1] = arr[j] - arr[j + 1];
					arr[j] = arr[j] - arr[j + 1];
					flag = 1;
					index = j + 1;
				}
				System.out.print(3);
			}
			if (flag == 0)
				return;
			i = index;
			
			for (int j = arr.length - 1; j > n; j--) {
				if (arr[j] < arr[j - 1]) {
					arr[j] = arr[j] + arr[j - 1];
					arr[j - 1] = arr[j] - arr[j - 1];
					arr[j] = arr[j] - arr[j - 1];
					flag = 1;
				}
			}
			n++;
			if (flag == 0)
				return;
		}
	}
测试算法效率
	public static void main(String[] args) {
		int[] arr1 = {0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
		bubbleSort(arr1);
		System.out.println();
		for (int i : arr1) {
			System.out.print(i + "\t");
		}
		System.out.println();
		
		
		int[] arr2 = {0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
		bubbleSortOptimize1(arr2);
		System.out.println();
		for (int i : arr2) {
			System.out.print(i + "\t");
		}
		System.out.println();
		
		
		int[] arr3 = {0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
		bubbleSortOptimize2(arr3);
		System.out.println();
		for (int i : arr3) {
			System.out.print(i + "\t");
		}
		System.out.println();
		
		int[] arr4 = {0, 1, 2, 3, 2, 82, 16, 13, 99, 100, 101, 102};
		bubbleSortOptimize3(arr4);
		System.out.println();
		for (int i : arr4) {
			System.out.print(i + "\t");
		}
		System.out.println();
	}

比较结果图
可以看到循环次数的比较 第三次改进之后的循环次数明显比前两种的低。

第三次之后还能再改进吗?

第二次改进时,当后面排好序时,不再进行比较,那么当前面排好序时,能否在逆序循环寻找最小值时不再进行比较。

	public static void bubbleSortOptimize3(int[] arr) {
		int index;
		int index1;
		int flag;
		int flag1;
		int n = 0;
		for (int i = arr.length - 1; i > 0; i--) {
			flag = 0;
			flag1 = 0;
			index = i;
			for (int j = n; j < i; j++) {
				if (arr[j] > arr[j + 1]) {
					arr[j] = arr[j] + arr[j + 1];
					arr[j + 1] = arr[j] - arr[j + 1];
					arr[j] = arr[j] - arr[j + 1];
					flag = 1;
					index = j + 1;
				}
				System.out.print(3);
			}
			if (flag == 0)
				return;
			i = index;
			
			index1 = 0;
			for (int j = arr.length - 1; j > n; j--) {
				if (arr[j] < arr[j - 1]) {
					arr[j] = arr[j] + arr[j - 1];
					arr[j - 1] = arr[j] - arr[j - 1];
					arr[j] = arr[j] - arr[j - 1];
					flag1 = 1;
					index1 = j - 1;
				}
				System.out.print(4);
			}
//			n++;
			n = index1;
			if (flag1 == 0)
				return;
		}
	}

结果为:
结果图看起来好像是提升了效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值