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

发布于:2025-05-28 ⋅ 阅读:(24) ⋅ 点赞:(0)

 

🔥「炎码工坊」技术弹药已装填!
点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】

 


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

场景描述

假设你是一家奶茶店的店员,每天营业结束后需要将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%彩蛋
(温馨提示:本工坊不打灰工,只烧脑洞🔥)

 


网站公告

今日签到

点亮在社区的每一天
去签到