经典再现,回顾常见排序算法之冒泡排序,附Java源码及优化改进实现

回顾一下排序算法,老酒装新瓶,给自己的技能点做个回放。

排序(Sorting) 是计算机程序设计中的一种重要操作,它的功能是将一个数据元素(或记录)的任意序列,重新排列成一个有序的序列,也可以理解为高矮个站队。

衡量排序算法的两个指标,时间复杂度 和 稳定性。

举个例子,如果我们的数据是:3 5 4 2 2, 稳定的排序最后的俩个2在排好序后他们的原始前后顺序是不会变的(第一个2还在第二个2的前面,有点绕,你可以理解为小明和小强一样高,最开始小明在小强的前面,排完序之后,小明还在小强前面,就属于稳定的排序),不稳定的排序最后两个2的顺序可能交换(也就是可能小明在前,也可能小强在前)。

时间复杂度先跳过哈,我回头单独写一篇文章介绍,本文主要介绍和实操"冒泡排序"。

介绍

冒泡排序是將比較大的數字移到序列的后面,较小的移到前面。

从第一个开始,第一个和第二个比,谁高(大)谁站后面(两个人(数)的位置交换,不是最后面),当前第二个再与第三个比,依次进行,一轮下来之后,筛选出来最高个(大)的人(数)。

上面就表示第一轮结束了,第二轮和第一轮一样,只是最后一个人(数)已经排好了,不用管他了。

经过 N-1 轮之后,排序完成。

N 个人,经过 N-1 轮,相当于 N*(N-1)=N^2-N, 时间复杂度取最大的 O(n^2)

实例

原始数据:

3 5 2 6 2

第一轮

比较 3 和 5,5 大于 3 ,不需交换

3 5 2 6 2

继续比较 5 和 2,5 大于 2,交换位置

3 2 5 6 2

继续比较 5 和 6,6 大于 5,不需交换

3 2 5 6 2

继续比较 6 和 2,6 大于 2,交换位置

3 2 5 2 6

6 移到最后,两个2都分别向前移动。

第二轮

比较 3 和 2, 3 大于 2,交换位置

2 3 5 2 6

比较 3 和 5, 5 大于 3,不需交换

2 3 5 2 6

比较 5 和 2, 5 大于 2,交换位置

2 3 2 5 6

不需比较 5 和 6

第三轮

比较 2 和 3, 3 大于 2,不需交换

2 3 2 5 6

比较 3 和 2, 3 大于 2,交换位置

2 2 3 5 6

不需比较了

第四轮

比较 2 和 2,不需交换

2 2 3 5 6

四轮结束,最终的结果:

2 2 3 5 6

Java 实现

复制代码
public class Bubble {

    /**
     * 冒泡排序
     */
    public static int[] sort(int[] array) {
        int temp;
        // 第一层循环表明比较的轮数, 比如 length 个元素,比较轮数为 length-1 次(不需和自己比)
        for (int i = 0; i < array.length - 1; i++) {
            System.out.println("第" + (i + 1) + "轮开始");
            // 第二层循环,每相邻的两个比较一次,次数随着轮数的增加不断减少,每轮确定一个最大的,不需比较那个最大的
            for (int j = 0; j < array.length - 1 - i; j++) {
                System.out.println("第" + (i + 1) + "轮,第" + (j + 1) + "次比较:");
                if (array[j + 1] < array[j]) {
                    temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
                for (int k : array) {
                    System.out.print(k + " ");
                }
                System.out.println();
            }
            System.out.println("结果:");
            for (int k : array) {
                System.out.print(k + " ");
            }
            System.out.println();
        }
        return array;
    }

    public static void main(String[] args) {
        int[] array = {3, 5, 2, 6, 2};
        int[] sorted = sort(array);
        System.out.println("最终结果");
        for (int i : sorted) {
            System.out.print(i + " ");
        }
    }

}

输出结果:

复制代码
第1轮开始
第1轮,第1次比较:
3 5 2 6 2 
第1轮,第2次比较:
3 2 5 6 2 
第1轮,第3次比较:
3 2 5 6 2 
第1轮,第4次比较:
3 2 5 2 6 
结果:
3 2 5 2 6 
第2轮开始
第2轮,第1次比较:
2 3 5 2 6 
第2轮,第2次比较:
2 3 5 2 6 
第2轮,第3次比较:
2 3 2 5 6 
结果:
2 3 2 5 6 
第3轮开始
第3轮,第1次比较:
2 3 2 5 6 
第3轮,第2次比较:
2 2 3 5 6 
结果:
2 2 3 5 6 
第4轮开始
第4轮,第1次比较:
2 2 3 5 6 
结果:
2 2 3 5 6 
最终结果
2 2 3 5 6 

优化改进

对冒泡排序常见的改进方法是加入一标志性变量 pos ,用于标志某一趟排序过程中是否有数据交换,如果进行某一趟排序时并没有进行数据交换(都不需要交换,肯定排好了),则说明数据已经按要求排列好,可立即结束排序,避免不必要的比较过程。

设置一标志性变量 pos,用于记录每趟排序中最后一次进行交换的位置(后面有多个没有发生交换,说明后面已经排好了)。由于 pos 位置之后的记录均已交换到位,故在进行下一趟排序时只要排到 pos 位置即可。

怎么理解呢?

3 2 4 5 6 为例

第一轮排序,发生交换的位置仅仅是 3 和 2, 则 pos 是 0(索引位置从0开始)

直接一轮就结束了,而不用傻傻的再跑4轮。

代码实现:

复制代码
public class Bubble {


    /**
     * 冒泡排序(优化改进版)
     */
    public static int[] sort(int[] array) {
        int temp;
        int time = 1;
        for (int i = array.length - 1; i > 0; ) {
            System.out.println("第" + time + "轮开始");
            int pos = 0;
            // 第二层循环,每相邻的两个比较一次,次数随着轮数的增加不断减少,每轮确定一个最大的,不需比较那个最大的
            for (int j = 0; j < i; j++) {
                System.out.println("第" + time + "轮,第" + (j + 1) + "次比较:");
                if (array[j + 1] < array[j]) {
                    // 记录最后一次交换位置的索引,下一轮只需排序到 pos 位置
                    pos = j;
                    temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
                for (int k : array) {
                    System.out.print(k + " ");
                }
                System.out.println();
            }
            // 之前是 i--, 优化后直接跳到最后交换位置的索引
            i = pos;
            time++;
            System.out.println("结果:");
            for (int k : array) {
                System.out.print(k + " ");
            }
            System.out.println();
        }
        return array;
    }

    public static void main(String[] args) {
        int[] array = {3, 2, 4, 5, 6};
        int[] sorted = sort(array);
        System.out.println("最终结果");
        for (int i : sorted) {
            System.out.print(i + " ");
        }
    }

}

结果输出:

复制代码
第1轮开始
第1轮,第1次比较:
2 3 4 5 6 
第1轮,第2次比较:
2 3 4 5 6 
第1轮,第3次比较:
2 3 4 5 6 
第1轮,第4次比较:
2 3 4 5 6 
结果:
2 3 4 5 6 
最终结果
2 3 4 5 6 

总结

好了,今天的分享就这些,关于冒泡排序,你学会了嘛?如果学会了,看懂了,请留下你的点赞,收藏,分享,关注。

有任何问题可以公作号:新质程序猿,可以找到我。

相关推荐
JavaGuide16 分钟前
JDK 25(长期支持版) 发布,新特性解读!
java·后端
用户37215742613517 分钟前
Java 轻松批量替换 Word 文档文字内容
java
白鲸开源18 分钟前
教你数分钟内创建并运行一个 DolphinScheduler Workflow!
java
CoovallyAIHub1 小时前
中科大DSAI Lab团队多篇论文入选ICCV 2025,推动三维视觉与泛化感知技术突破
深度学习·算法·计算机视觉
Java中文社群1 小时前
有点意思!Java8后最有用新特性排行榜!
java·后端·面试
代码匠心1 小时前
从零开始学Flink:数据源
java·大数据·后端·flink
间彧1 小时前
Spring Boot项目中如何自定义线程池
java
间彧2 小时前
Java线程池详解与实战指南
java
用户298698530142 小时前
Java 使用 Spire.PDF 将PDF文档转换为Word格式
java·后端
NAGNIP2 小时前
Serverless 架构下的大模型框架落地实践
算法·架构