冒泡排序:像煮汤一样让数字「冒泡」

🔥「炎码工坊」技术弹药已装填!

点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】


一、问题驱动:为什么需要冒泡排序?

场景描述

假设你是一家奶茶店的店员,每天营业结束后需要将20杯奶茶的销量数据按从小到大排序,以便统计热门款。如果手动排序效率低,如何用代码快速解决?

核心矛盾

  • 数据量小(20个数),不需要复杂算法
  • 需要直观、易实现的方案(新手友好)
  • 稳定性要求高(相同销量的奶茶不能乱序)

冒泡排序正是这种场景下的理想选择:简单、稳定、无需额外空间。


二、冒泡排序原理:煮汤的比喻

冒泡排序就像煮一锅汤:

  1. 搅拌动作:相邻元素两两比较(像气泡碰撞)
  2. 大气泡上浮:每轮遍历将当前最大值移动到数组末尾
  3. 重复加热:直到所有元素有序

算法步骤(以 [5, 3, 8, 1] 为例)

  1. 第1轮:找出最大值 8

    复制代码
    [5,3,8,1] → [3,5,8,1] → [3,5,8,1] → [3,5,1,8]  
  2. 第2轮:找出次大值 5

    复制代码
    [3,5,1,8] → [3,5,1,8] → [3,1,5,8]  
  3. 第3轮:找出第三大值 3

    复制代码
    [3,1,5,8] → [1,3,5,8]  

三、Java代码实现(JDK 17)

复制代码
import java.util.Arrays;

public class BubbleSort {
    // 基础版冒泡排序
    public static void bubbleSort(int[] arr) {
        boolean swapped; // 标记是否发生交换
        for (int i = 0; i < arr.length - 1; i++) {
            swapped = false;
            // 每轮减少一个已排序的元素
            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;
                    swapped = true;
                }
            }
            // 若本轮无交换,说明已有序
            if (!swapped) break;
        }
    }

    // 鸡尾酒排序(双向冒泡)
    public static void cocktailSort(int[] arr) {
        int start = 0;
        int end = arr.length - 1;
        boolean swapped = true;

        while (swapped) {
            swapped = false;

            // 从左到右:找最大值
            for (int i = start; i < end; i++) {
                if (arr[i] > arr[i + 1]) {
                    swap(arr, i, i + 1);
                    swapped = true;
                }
            }
            if (!swapped) break;
            end--; // 缩小右边界

            // 从右到左:找最小值
            for (int i = end; i > start; i--) {
                if (arr[i] < arr[i - 1]) {
                    swap(arr, i, i - 1);
                    swapped = true;
                }
            }
            start++; // 缩小左边界
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }

    public static void main(String[] args) {
        int[] sales1 = {5, 3, 8, 1};
        bubbleSort(sales1);
        System.out.println("基础版排序结果: " + Arrays.toString(sales1)); // 输出: [1, 3, 5, 8]

        int[] sales2 = {2, 3, 4, 5, 6, 7, 8, 1};
        cocktailSort(sales2);
        System.out.println("鸡尾酒排序结果: " + Arrays.toString(sales2)); // 输出: [1, 2, 3, 4, 5, 6, 7, 8]
    }
}

四、方案对比:如何选择实现方式?

实现方案 时间复杂度(平均) 空间复杂度 稳定性 适用场景
基础版 O(n²) O(1) 稳定 教学演示、小型数据集
优化版 O(n²)~O(n) O(1) 稳定 数据部分有序的情况
鸡尾酒排序 O(n²) O(1) 稳定 需双向优化的极端场景

优化点说明

  • 基础版缺陷:即使数据已有序,仍会进行所有轮次比较
  • 优化版改进 :通过 swapped 标志提前终止无效遍历(如输入 [1,2,3,4,5] 时仅需1轮遍历)
  • 鸡尾酒排序:双向遍历(先找最大后找最小),适合「部分有序但两端混乱」的数据

鸡尾酒排序实战案例

以数组 [2,3,4,5,6,7,8,1] 为例:

  1. 基础版冒泡排序 :需要 7轮 遍历才能将 1 移动到最前
  2. 鸡尾酒排序 :仅需 3轮 即可完成排序
    • 第1轮:从左到右将 8 移动到末尾,从右到左将 1 移动到最前
    • 第2轮:处理中间未排序部分 [2,3,4,5,6,7]
    • 第3轮:验证已完全有序

五、可视化流程图


六、专有名词说明表

术语 英文全称 解释说明
冒泡排序 Bubble Sort 通过相邻元素交换实现的排序算法
时间复杂度 Time Complexity 衡量算法运行时间随输入规模增长的趋势
空间复杂度 Space Complexity 衡量算法所需额外存储空间的指标
稳定性 Stability 相同元素排序后相对位置是否改变
鸡尾酒排序 Cocktail Shaker Sort 双向冒泡排序,交替从头尾开始比较
优化标志 Swap Flag 判断是否提前终止排序的布尔变量
最后交换位置 Last Swap Index 记录最后一次交换的位置以缩小遍历范围

总结:冒泡排序是学习排序算法的「Hello World」,虽然效率不如快速排序,但在小型数据集和教学场景中仍有价值。掌握其核心思想(两两比较、逐轮冒泡)是理解更复杂算法的基石。对于部分有序的数据(如奶茶店销量数据),鸡尾酒排序能显著减少遍历次数,是值得尝试的优化方案。

🚧 您已阅读完全文99%!缺少1%的关键操作:

加入「炎码燃料仓」

🚀 获得:

√ 开源工具红黑榜 √ 项目落地避坑指南

√ 每周BUG修复进度+1%彩蛋

(温馨提示:本工坊不打灰工,只烧脑洞🔥)

相关推荐
咖啡八杯1 小时前
GoF设计模式——解释器模式
java·后端·spring·设计模式
优橙教育1 小时前
5G网优培训 vs Java开发:转行选哪个?
java·开发语言·5g
糖果店的幽灵1 小时前
【DeepAgents 从入门到精通】Context Management 上下文管理
java·人工智能·后端·spring·中间件·langgraph·deepagents
腻害兔3 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
碎光拾影3 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库
Miao121314 小时前
微服务 API 测试实践:海外某民宿平台如何构建模式驱动测试基础设施
java·开发语言
腻害兔4 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:支付模块 yudao-module-pay,一个让产品经理都看懂的支付中台设计
java·前端·vue.js·产品经理·ai编程
CRMEB系统商城5 小时前
开源自建还是SaaS订阅?算一笔3年经济账
java·大数据·开发语言·开源
keyipatience6 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
weixin_408099677 小时前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能