排序算法之冒泡排序

一、写在前面的话

  今天在地铁上看到有博主分析时间复杂度,提到冒泡排序的时间复杂度是O(n²) 。我竟然想起这么多年没有再写过冒泡了,于是乎自己再动手整理一遍算是复习也是新的学习。

二、冒泡的思想

  冒泡的思想其实就是两两比较,每趟都能确定一个最大/最小的数值在最末尾。

  那举例来说明,例:我们要将数组int[] a = {7,6,5,4,3,2,1}做正序排序。这是一个比较极端的情况。我们来分析一下冒泡的思想。

 它会怎么做?

  1.a[0]和a[1]比较,a[0]>a[1] == true ? a[0] 交换至a[1]的位置 : a[0]原封不动

  2.a[1]和a[2]再做相同操作,直到a[a.length-2]和a[length-1]比较完毕。

  故此,我们的结果是

  /**

  * 6,5,4,3,2,1,7 

  * 5,4,3,2,1,6,7

  * 4,3,2,1,5,6,7

  * 3,2,1,4,5,6,7

  * 2,1,3,4,5,6,7

  * 1,2,3,4,5,6,7

  */

三、码上见

  按照刚才的思想,我们编写如下代码:

Integer[] a = new Integer[] {7,6,5,4,3,2,1};
		int temp = 0;
		for (int i = 0; i < a.length; i++) {
			for (int j = 0; j < a.length-1; j++) {
				if(a[j] > a[j+1]) {
					 temp = a[j];
					 a[j] = a[j+1];
					 a[j+1] = temp;
				}
			}
		}


/*------------------------- 排序后的结果----------------------*/

1	2	3	4	5	6	7

大家有没有注意到,按照冒泡的思想我们只需要走a.length-1次就可以完成整个操作 ,而上面的代码走了a.length次。

另外,每次都可以在尾部确立一个最大数,那除去第一次比较其他次数有必要再和最大值作比较吗?我们可以减掉外层循环的变量刚好规避掉这个问题。所以我们的排序可以变为:

 /**

 

  * 6,5,4,3,2,1,           7  确立了7是最大下次7不参与 排序完i=1

 

  * 5,4,3,2,1,         6,7  确立了6是最大,但该趟排序的6没有与7比较,因为内循环减掉了i

 

  * 4,3,2,1,       5,6,7  同上,5不与6比较...

 

  * 3,2,1,     4,5,6,7

 

  * 2,1,   3,4,5,6,7

 

  * 1,  2,3,4,5,6,7 最后一趟第一位一定是最小的数值了 

                    因为大家都两两比较过

                    就算最极端的情况最小的数在最末尾

                    它也被带到了a[0]的位置上。故此可以不用比较了

  */

代码变为:

Integer[] a = new Integer[] {7,6,5,4,3,2,1};
		int temp = 0;
		for (int i = 0; i < a.length-1; i++) { // 第一位不参与比较可以减少一次
			for (int j = 0; j < a.length-1-i; j++) { //最大位数不参与二次比较 减掉i
				if(a[j] > a[j+1]) {
					 temp = a[j];
					 a[j] = a[j+1];
					 a[j+1] = temp;
				}
			}
		}

ok,优化完毕了。目前还有一个问题没有考虑,我们是用最极端的情况,那有没有最优情况呢?

比如我们需要排序的数组为:int[] a = {1,2,3,4,5,6,7}

相比较上面的情况有什么区别呢?对喽,就是我们第一趟比较的时候发现我们if的条件没有一个成立的

此时我们根据发现再来优化。

Integer[] a = new Integer[] {1,2,3,4,5,6,7};
		int temp = 0;
		boolean flag = false;//设立flag检测
		for (int i = 0; i < a.length-1; i++) { // 第一位不参与比较可以减少一次
			for (int j = 0; j < a.length-1-i; j++) { //最大位数不参与二次比较 减掉i
				if(a[j] > a[j+1]) {
					 temp = a[j];
					 a[j] = a[j+1];
					 a[j+1] = temp;
					 //改变flag
					 flag = true;
				}
			}
			//当第一趟比较完我们来检查flag的值
			if(!flag)
				break;//直接跳出,说明是完全有序的状态
		}

 OK。讲完了。

四、总结

  现在来想想地铁上看到的博主分享的冒泡排序的时间复杂度。没错,一般情况下他的时间复杂度就是O(N²)。那如果是最优情况的话只需要比较n-1替换0,所以时间复杂度可以是O(n)。

  OK,以上。有不足之处欢迎指正共同学习进步!

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值