图解算法:冒泡排序

关注下方公众号,分享硬核知识

作者 | 小K

出品 | 公众号:小K算法 (ID:xiaok365)

01

故事起源

幼儿园放学,小朋友们集合,需要先从低到高排队,应该怎么排呢?

02

开始行动

小K身高180,是班里最高的,自然得往后排啦。小K先和身后的小B比较,然后和小B交换。

小K接着和身后的小D比较,然后和小D交换。

经过和4个小朋友交换位置,小K终于找到自己的位置啦。

上面的过程其实就是冒泡排序的核心思想了。

03

冒泡排序

为描述方便,用下面的数组模拟小朋友的交换过程。

核心思想(升序):
从首位置开始,依次比较前后两个数,如果前面的数比后面的数大,就交换两个数。这样第1轮结束后,最大的数就会移动到最后的位置。对剩余元素重复执行N-1次,整个数组有序。因为像空气上浮到水面,最大的元素会慢慢浮到最后,所以冒泡因此得名。

3.1

第1轮

执行完成后,最大的元素归位。

3.2

第2轮

第2轮接着对前面剩余的N-1个元素重复上面步骤,第2大的元素归位。

3.3

第3轮

第3轮对前面剩余的N-2个元素重复上面步骤,第3大的元素归位。

总共执行N-1次操作,所有元素归位。

3.4

代码实现

for (int i = 0; i < n - 1; ++i) {
    for (int j = 0; j < n - i - 1; ++j) {
        if (a[j] > a[j + 1]) {
            swap(a[j], a[j + 1]);
        }
    }
}

04

问题及优化

4.1

迭代轮次优化

如果原数组为如下情况,那么在执行完第1轮后,整个数组已经有序,后面的轮次没必要执行,可以针对这种情况做一次优化改进。
改进点1:
如果某一轮没有发生过交换,说明数组已经有序,那么以后也不会发生交换,此时可以终止迭代。

代码实现

for (int i = 0; i < n - 1; ++i) {
    // flag标记是否有交换
    bool flag = true;
    for (int j = 0; j < n - i - 1; ++j) {
        if (a[j] > a[j + 1]) {
            swap(a[j], a[j + 1]);
            flag = false;
        }
    }
    if (flag) {
        break;
    }
}

4.2

扫描范围优化

如果为以下情况,我们会发现最后的6和8所处的位置和最终排序完成的位置一样,说明过程中他们的位置不会发生变化。

上一轮最后交换的位置,在下一轮时,此位置后面的数也不会再发生交换。

改进点2:
记录每一次最后发生交换的位置,下一轮只需要扫描到此位置的前一个即可。

代码实现

// 记录最后交换的位置
int position = 0;
int len = n - 1;
for (int i = 0; i < n - 1; ++i) {
    // flag标记是否有交换
    bool flag = true;
    for (int j = 0; j < len; ++j) {
        if (a[j] > a[j + 1]) {
            swap(a[j], a[j + 1]);
            flag = false;
            position = j;
        }
    }
    len = position;
    if (flag) {
        break;
    }
}

05

总结

冒泡排序是比较简单的一种排序算法,核心思想就是比较相邻的两个数,但效率比较低所以可做一些优化。时间复杂度为O(N^2),数据规模较小时可采用,但数据过大时就不建议采用冒泡了。

本文原创作者:小K,一个思维独特的写手。
文章首发平台:微信公众号【小K算法】。

如果喜欢小K的文章,请点个关注,分享给更多的人,小K将持续更新,谢谢啦!

关注下方公众号,分享硬核知识

关注我,涨知识

原创不易,感谢分享

转发,点赞,在看

往期精彩回顾

巴什博弈:取石子游戏

逻辑面试题:猴子搬香蕉

逻辑面试题:1+1=2最复杂的打开方式

分享给更多朋友,转发,点赞,在看

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值