当前位置: 首页 > news >正文

排序算法系列之(二)——冒泡排序名字最为形象的一个

前言

大约在上个冬季我给自己挖了一个坑(想要总结排序~~(>_<)~~),感觉把自己埋起来会暖和一点,可是大约一年过去了,埋的越来越深,却丝毫感觉不到暖意……被我的诗意打动了有没有,已经深深的折服了有没有,呵呵,我自己都不信!

还是继续来说说排序,距离上一篇排序总结《排序算法系列之(一)——选择排序清新脱俗的一面》2017-02-15 16:29已经过去了大半年的时间,代码越敲越多,但总结往往跟不上了,加油吧!

冒泡排序

那么言归正传,接下来我们请出今天的主角——冒泡排序。老规矩,我们不讲时间复杂度、不讲空间复杂度、不讲算法的优缺点,我们就来聊聊自己的理解,讲讲它为什么起了一个好名字——冒泡,话说这么多种排序算法,只有冒泡排序的名字起得这么形象。

提到冒泡你会想到什么,不管你想到了什么,反正我想到了烧水的场景,水中的气泡随着温度的上升越来越大,根据XXX原理可知,气泡在水里待不住了,然后它缓慢地从水底移动到水面,然后爆开,只要你烧过水,这个画面一定能够脑补出来。

其实冒泡排序和这个过程像极了,我们这次拿5个橘子来表演一下冒泡排序,5个大小不同的橘子排成一列,注意是一列,今天为了将冒泡排序不再用横排了,因为一列的橘子能分清上下,假设最下面的橘子是第1个,最上面的橘子是第5个,从下到上来模拟气泡从锅底冒出来的过程。

比如我们要从小到大排列,现在我们可以开始冒泡了,看看第1个橘子,再看看第2个,如果第1个比较大,那么把它和第2换下位置,也就是把大个的冒上去。

然后看看第2个橘子,在看看第3个橘子,如果第2个比较大,那么把第2个橘子和第3个橘子换一下位置,否则不交换,然后继续依次往后看,最后我们会看到第4个橘子和第5个橘子,同样的第4个比较大就交换,否则不动。

完成上述过程后,想象一下我们到底做了什么,我们实际上找到了最大的橘子,并且把它从下面的某个位置“冒泡”到了最上边,其实这就是网上常常所说的一趟排序,既然最大的橘子都到最上边了,所以它不需要再参与后面的排序过程。

下面来进行第二次冒泡,继续看看第1个橘子,再看看第2个,如果第1个比较大,那么把它和第2个换下位置,否则不动,依次进行,最后看看第3个橘子,再看看第4个,如果第3个比较大,那么把它和第4个换下位置,为什么是这次就比较到第4个呢,因为上一次冒泡第5个已经是最大的了,不需要再跟它比了,而这一次冒泡过后我们第4个橘子也变成第二大的了,不会再参与后面的排序。

有没有发现我们的范围在缩小,每次都能减少一个橘子的位置,那么想想一下一共5个橘子,我们需要几次冒泡才能排序完成?4次!注意是4次而不是5次,因为最后一次只剩下第一个橘子没有排序了,它肯定是最小的,不用再排了,这就是为什么冒泡排序的最外层的循环次数是N-1。

而我们每一次排序的最后一个都会减少1个,所以冒泡排序的第二层循环的结尾要减掉排序次数,依照这个思路很容易就能实现代码,并且也不会把边界弄错,搞出冒泡排序写成选择排序的笑话。

代码实现

/*
功能: 冒泡排序,实现数组元素从小到大排列
参数: array--表示待排序的数组,此处会退化成指针
        count--数组元素的个数
返回值:无
注意: 只用来表示思路,不考虑指针为空等特殊情况
*/
void bubble_sort(int array[], int count)
{
    for (int bubble_count = 0; bubble_count < count - 1; ++bubble_count)
    {
        for (int bubble_pos = 0; bubble_pos < count - 1 - bubble_count; ++bubble_pos)
        {
            if (array[bubble_pos] > array[bubble_pos + 1])
            {
                swap_data(&array[bubble_pos], &array[bubble_pos + 1]);  // 交换数据
            }
        }
    }
}

/*
功能: 交换两个变量
参数: element1--被交换的第一个元素的地址
        element2--被交换的第二个元素的地址
返回值:无
注意: 只用来表示思路,不考虑指针为空等特殊情况
*/
void swap_data(int* element1, int* element2)
{
    int middle_value = *element1;
    *element1 = *element2;
    *element2 = middle_value;
}

如果你跟着橘子的冒泡的思路走下来,相信你很容易就能理解这个算法实现,并且可以注意到边界条件的问题,代码就像上面这样,如果觉得我理解的有问题或者代码有错,也欢迎大家批评指正。

运行测试

冒泡排序–源码

如果你想运行测试一下,可以复制或者下载源代码,在本机运行测试一下,当然也可以选择在线编辑器,把源代码复制到网页中运行查看结果。

相关文章:

  • Python查找文件中包含中文的行
  • sscanf类似于正则表达式的进阶用法
  • mysql函数扩展之UDF开发
  • Python实现一个简单的图片爬虫
  • 验证mysql联合索引最左原则
  • Mysql查询时case when语句的使用
  • Vim中简单格式化代码
  • Vim、Xshell、远程终端莫名卡死的原因
  • 关于游戏中仓库类的设计
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • 神秘莫测的时间复杂度
  • 排序算法系列之(三)——略显神秘的快速排序
  • .bat批处理(六):替换字符串中匹配的子串
  • 操作指向类成员的指针需要了解的两个操作符-*和.*
  • VS2015调试dump文件时提示未找到xxx.exe或xxx.dll
  • codis proxy处理流程
  • ES6简单总结(搭配简单的讲解和小案例)
  • Intervention/image 图片处理扩展包的安装和使用
  • js中的正则表达式入门
  • vue中实现单选
  • Yii源码解读-服务定位器(Service Locator)
  • 问题之ssh中Host key verification failed的解决
  • 阿里云服务器购买完整流程
  • 基于django的视频点播网站开发-step3-注册登录功能 ...
  • ​LeetCode解法汇总2808. 使循环数组所有元素相等的最少秒数
  • # 再次尝试 连接失败_无线WiFi无法连接到网络怎么办【解决方法】
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • $.each()与$(selector).each()
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (floyd+补集) poj 3275
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (七)MySQL是如何将LRU链表的使用性能优化到极致的?
  • (数据结构)顺序表的定义
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (转)Oracle存储过程编写经验和优化措施
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .aanva
  • .mysql secret在哪_MYSQL基本操作(上)
  • .NET C# 使用 SetWindowsHookEx 监听鼠标或键盘消息以及此方法的坑
  • .net core Swagger 过滤部分Api
  • .net core webapi 部署iis_一键部署VS插件:让.NET开发者更幸福
  • .net 后台导出excel ,word
  • .NET/C# 使窗口永不获得焦点
  • .NetCore 如何动态路由
  • .net操作Excel出错解决
  • .NET开源的一个小而快并且功能强大的 Windows 动态桌面软件 - DreamScene2
  • .net最好用的JSON类Newtonsoft.Json获取多级数据SelectToken
  • @DataRedisTest测试redis从未如此丝滑
  • @ModelAttribute注解使用
  • @reference注解_Dubbo配置参考手册之dubbo:reference
  • @require_PUTNameError: name ‘require_PUT‘ is not defined 解决方法
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [BZOJ2281][SDOI2011]黑白棋(K-Nim博弈)
  • [C++]C++基础知识概述