冒泡排序分从大到小和从小到大两种排序方式。它们的唯一区别就是两个数交换的条件不同,从大到小排序是前面的数比后面的小的时候交换,而从小到大排序是前面的数比后面的数大的时候交换。我这里只说 从小到大的排序方式。

冒泡排序的原理:从第一个数开始,依次往后比较,如果前面的数比后面的数大就交换,否则不作处理。这就类似烧开水时,壶底的水泡往上冒的过程。

一、 图解分析

现以数组[8,7,6,4,5]为例,我们通过将这个数组按从小到大的方式排序,来说明冒泡排序的过程。

第一次循环:此次循环的多次比较交换,使最大的数字8冒到最上面。


第二次循环:此次循环中的多次比较和交换,使7往上冒,最终排到倒数第二个位置。


你会发现,这次循环比前面少一次循环比较。

这是因为第一次循环时已经把最大的8排到最上面的位置了,这次排序肯定不会去占用最上面的位置的,所以此时比较次数可以比前面少一次。

第三次循环:同理,此时6会往上冒。比较次数同理又会比前面少一次。


此时看着最后的结果已经是从小到大了,这是因为在原始数组中,5就在4的上面。

但实际我们不知道5是在4的上面,我们就得继续完成最后一次循环比较。

第四次循环: 5已经排在4的上面了,比较后不交换。


二、代码实现

总结前面的图解,数组长度设为n。外层共循环了n-1次,外层循环增加一次,对应内层循环就 减少一次。
外层循环为:for (int i = 0; i < arr.length-1; i++)
内层循环为:for (int j = 0; j < arr.length - 1 - i; j++)

int[] arr = {8, 7, 6, 4, 5};
        
        for (int i = 0; i < arr.length-1; i++) {
        
            for (int j = 0; j < arr.length - 1 - i; j++) {
            
                if (arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
                
            }
            
        }
需要注意的是,在里层的for循环里,j的取值范围是arr.lenght - 1 - i。

三、冒泡排序算法的优化

具体的优化得看具体的情况

1. 减少外层循环次数的优化

如有数组[8,7,6,1,2,3,4,5],当我们将8、7、6三个数都排在后面后,其实就不需要继续循环比较了。

那我们如何知道的面不再需要比较了呢?答案就是如果该次循环没有发生一次数的交换,就说明数组已经排好序了,那么后面的循环比较就可以停止了。

代码如下:

int[] arr = {8, 7, 6, 1, 2, 3, 4, 5};
        
        // flag: 在一次循环中是否发生过数据交换。true:表示发生过交换,false:表示未发生过交换
        boolean flag = true;
        
        for (int i = 0; i < arr.length - 1; i++) {
            // 如果未发生交换,则break
            if (!flag) {
                break;
            }
            flag = false; // 每次循环都先置为false,即认为不会发生交换
            for (int j = 0; j < arr.length - i - 1; j++) {
                if (arr[j] > arr[j + 1]) {
                    flag = true;// 发生了交换
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
            System.out.println(i);
        }
从输出结果看,外层循环只循环了4次,而不会是7次。

2. 减少内层循环次数的优化

如有数组[2, 4, 3, 1, 5, 6, 7, 8, 9],你会发现,从5开始都是不用比较和循环了。所以我们要想办法减少后面的循环和比较。

我们可以发现,当我们把4交换到5前面后,后面的每次循环里都不再发生交换。即,如果我们将第一次出现该次不再交换数据时的位置下标找到,然后把这个值作为内层循环j的上限值。这样内层循环就会减少一些循环。所以内层循环的 j 的上限值是动态值。

代码如下:

int[] arr = {4, 2, 3, 1, 5, 6, 7, 8, 9};
        
        // flag: 在一次循环中是否发生过数据交换。true:表示发生过交换,false:表示未发生过交换
        boolean flag = true;
        
        // 上一次内层循环上界值,在第一次循环时与arr.length-1-i相等,即:arr.length-1。也就是说默认是最后一个
        int k = arr.length - 1;
        
        for (int i = 0; i < arr.length - 1; i++) {
            // 如果未发生交换,则break
            if (!flag) {
                break;
            }
            
             // 每次循环都先置为false,即认为不会发生交换
            flag = false;
            
            // 记录上一次内层循环时最后一次交换的位置
            int last = 0;
            
            for (int j = 0; j < k; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 发生了交换
                    flag = true;
                    // 记录每次交换的位置
                    last = j;
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                } 
            }
            // 让下一次循环的上界值变成此次循环的最后一次交换的位置
            k = last; 
        }

k为动态值有个好处,即随时动态调整上一次最后交换的位置。这样做的好处是,当遇到数组中有紧挨着的数是连续的时候就会在下一次循环时省略它们的比较。
————————————————
版权声明:本文为CSDN博主「zcl_love_wx」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/zcl_love_wx/article/details/83576962

排序算法(2)冒泡排序相关推荐

  1. Java排序算法:冒泡排序

    Java排序算法:冒泡排序 //创建数组并赋值int[] data = new int[] {11,10,55,78,100,111,45,56,79,90,345,1000};for(int i=0 ...

  2. 排序算法:冒泡排序、插入排序、选择排序、希尔排序

    相关博客: 排序算法:冒泡排序.插入排序.选择排序.希尔排序 排序算法:归并排序.快速排序 排序算法:桶排序.计数排序.基数排序 排序算法:堆排序 十大排序算法小结 一.冒泡排序: 1.算法原理: 冒 ...

  3. golang 排序_常用排序算法之冒泡排序

    周末无事,带娃之余看到娃娃在算数,想到了排序-尝试着把几种常用的排序算法跟大家聊一聊,在分析的后面我会用GoLang.PHP和JS三种语言来实现下. 常见的基于选择的排序算法有冒泡排序.插入排序.选择 ...

  4. 十大排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序、基数排序

    冒泡排序.选择排序.插入排序.希尔排序.归并排序.快速排序.堆排序.计数排序.桶排序.基数排序的动图与源代码. 目录 关于时间复杂度 冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 ...

  5. 数据结构与算法:十大排序算法之冒泡排序

    数据结构与算法:十大排序算法之冒泡排序 package array;import java.util.Arrays;//冒泡排序 //1.比较数组中两个相邻的元素,如果第一个数比第二个数大,我们就交换 ...

  6. 【排序算法】冒泡排序、简单选择排序、直接插入排序比较和分析

    [排序算法]冒泡排序.简单选择排序.直接插入排序比较和分析 写在前面: 本文简单介绍了冒泡排序.简单选择排序.直接插入排序,并对这三种排序进行比较,入参都是80000个随机数,比较算法耗时.进一步,我 ...

  7. 排序算法(1)冒泡排序

    排序算法(1)冒泡排序 原理: 1.比较相邻的元素.如果第一个比第二个大,就交换他们两个. 2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大的数. 3. ...

  8. php编写冒泡排序算法_PHP排序算法之冒泡排序(Bubble Sort)实现方法详解

    本文实例讲述了PHP排序算法之冒泡排序(Bubble Sort)实现方法.分享给大家供大家参考,具体如下: 基本思想: 冒泡排序是一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换 ...

  9. 冒泡和快速排序的时间复杂度_常用排序算法之冒泡排序

    周末无事,带娃之余看到娃娃在算数,想到了排序-尝试着把几种常用的排序算法跟大家聊一聊,在分析的后面我会用GoLang.PHP和JS三种语言来实现下. 常见的基于选择的排序算法有冒泡排序.插入排序.选择 ...

  10. 排序算法之冒泡排序(Java版)

    排序:即使集合或数组中的元素有序化 本篇介绍最简单.最易掌握的冒泡排序 冒泡排序:         是一种简单的排序算法, 冒泡排序就像学生站队一样,要在老师的引导下,以某位同学位基准,其他学生按身高 ...

最新文章

  1. OpenCV使用 GrabCut 算法进行交互式前景提取
  2. jvm系列(六):Java服务GC参数调优案例
  3. 排序(3)---------冒泡排序(C语言实现)
  4. mysql期末考试试卷_MySQL数据库考试试题及答案
  5. 一个数里有那些约数用c++怎么做_如何从一堆数里找出哪几个数相加等于你要的值?...
  6. DCMTK:转换dicom文件编码
  7. linux c 文件映射,linuxc试题
  8. python断点续传下载_python requests 断点续传下载
  9. 全球首个企业云计算平台初探
  10. 局域网服务器时间自动校准,实现局域网内服务器时间同步的方法
  11. Android 系统(44)---多语言
  12. html毕业设计任务要求,毕业设计任务及进度安排|毕业设计进度安排
  13. 【C语言】下标法 编写数组元素的输入与输出
  14. 2021年国考申论写作之如何快速改进作文书写
  15. vsftp配置虚拟账户
  16. vue移动端上传文件插件_轻量级Vue图片上传插件——Vue-core-image-Upload
  17. 领存技术至强 E5-2648L 6U VPX 通用密集计算刀片
  18. 使用百度地图时如何隐藏百度地图logo
  19. java Excel导入(兼容格式xls和xlsx)
  20. autobahn-java-master,禁用自动配置

热门文章

  1. 关于3D打印文件格式:STL、OBJ、AMF、3MF的详解
  2. 学习笔记(01):10小时掌握区块链开发教程-2小时构建以太坊智能合约-1
  3. linux创建隐藏用户,Linux之隐藏权限lsattr和chattr
  4. 翻译记忆软件-塔多思TRADO经典教程_2
  5. idea 安装 jclasslib
  6. 初级Java程序员如何快速提升自己的能力?
  7. WIN10 LTSC 转 WIN10 专业版(纯净)
  8. word参考文献乱码问题
  9. Gulp简明使用教程
  10. 【MATLAB中UIGETFILE函数的用法】