算法--排序--冒泡排序--JAVA

冒泡排序有多种不同的写法,其中主要的区别就是性能的不同

这篇文章将逐步改进冒泡排序,使得冒泡排序不断进化

原始人

先看代码


	public void getSortArray(int array[]) {	
		int temp = 0; 
		for (int i = 0; i < array.length - 1; i++) {
			for (int j = 0; j < array.length - i - 1; j++) {
				if (array[j] > array[j + 1]) { 
					temp = array[j];
					array[j] = array[j + 1];
					array[j + 1] = temp;
				}
			}
		}
	}

原始人的代码就是简单 ,简单看看就能看的差不多,这里面有一个很重要的地方:i 与 j 的取值问题

我当时看到代码时不仅要问,i 与 j 为什么要这样取值呢?

答曰:

  • 对于 i 的 取值 :冒泡排序的目的就是 通过每次的交换,将最大的值交换到一串数字的最后,因为 i 是最外层循环的控制变量,因此 i 就代表着循环的次数,假设外层循环了3次 ,那么这串数字的最后3个数就已经有序了。所以,如果这串数字长度为 n ,那么显然外层只要循环 n - 1 次就使得数列有序了。因此外层循环次数为 array.length -1 次。

  • 对于 j 的取值:n 次外层循环使得数列最后 n 个为有序而且有序区的每个数必然比前面的都大,因此在每次的内层循环,没有必要再让 j 从 0 --> array.length - 1,只要从 0 --> array.length - i - 1

原始人进化

先看代码

	public void secondSortArray(int array[]) {
		int temp = 0;
		boolean sorted = false;
		for (int i = 0; i < array.length - 1; i++) {
			sorted = false;
			for (int j = 0; j < array.length - i - 1; j++) {
				if (array[j] > array[j + 1]) {
					temp = array[j];
					array[j] = array[j + 1];
					array[j + 1] = temp;
					sorted = true; 
				}
			}
			if(sorted == false) {
				break;
			}
		}
	}

最重要的就是添加了 sorted 这个布尔变量

为什么要添加这个变量呢?

看一个数列:1 2 3 4 5 8 7 显然这个序列只通过一次就可以有序,但是实际上要经过 21 次循环

  • 求冒泡排序(原始人阶段) 的计算公式:n(n-1)/ 2 其中 n 为数列的长度

这显然太耗费时间了,加上一个布尔变量,如果一次内部循环没有经过变量交换,那么就说明已经排序完成了,因此就结束排序。

原始人再进化

看代码

	public void thirdSortArray(int array[]) {
		int temp = 0;
		int count = 0;
		int boundary = array.length - 1;
		boolean sorted = false;
		for (int i = 0; i < array.length - 1; i++) {
			sorted = false;
			for (int j = 0; j < boundary; j++) {
				count++;
				if (array[j] > array[j + 1]) {
					temp = array[j];
					array[j] = array[j + 1];
					array[j + 1] = temp;
					sorted = true;
					boundary = j;
				}
			}

			if (sorted == false) {
				break;
			}
		}
	}

例如 2 1 3 5 6 7 8 这个数列,如果让我们人来进行排序,那么你会怎么做?我们会找一个边界,这个边界的右侧都是比左侧大的数而且已经有序,此后就只看这个边界左侧的数字。

那么把这个事情交给程序呢?我们也需要让程序找到这个边界,这个边界找到了,那么此后程序再进行数字比较的时候就更加省时省力。

如何让程序找到这个边界?重中之重就是:找到最后一次进行两数字交换的位置,这个位置就是边界!

知道了这里,那么代码也就很好看懂了(代码引进了第一次进化)

为了说明三者之间效率的差距,在内层循环设置一个变量count 计算整个排序过程的执行次数

	public void firstSortArray(int array[]) {
		int temp = 0;
		int count = 0;
		for (int i = 0; i < array.length - 1; i++) {
			for (int j = 0; j < array.length - i - 1; j++) {
				count++;
				if (array[j] > array[j + 1]) {

					temp = array[j];
					array[j] = array[j + 1];
					array[j + 1] = temp;
				}
			}
		}
		System.out.println("执行次数:"+count);
	}

另外两个的代码我就不贴了

对[ 2, 1, 3, 4, 5,6] 这个数组进行排序,得到结果分别为:

执行次数:15
最终结果:123456
执行次数:9
最终结果:123456
执行次数:5
最终结果:123456

可以看到,效率差距还是很明显的

详细代码:https://github.com/kai123wen/SUANFA/tree/master/%E6%8E%92%E5%BA%8F/%E5%86%92%E6%B3%A1%E6%8E%92%E5%BA%8F

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值