“体育课排队”​​ 的故事理解冒泡、选择、插入排序

87 阅读5分钟

用一个 ​​“体育课排队”​​ 的故事,结合代码手把手带你理解三大基础排序算法。​​一句话核心:排序就是让混乱的数据像队伍一样按高矮站好!​​👇


📣 ​​一、冒泡排序:相邻比较,大个子往后站​

​体育课故事​​:体育老师让10个同学随机站队(数组),要求从左到右从矮到高排队。老师从队首开始:

  • ​第1轮​​:老师让第1和第2个同学比身高,如果左边>右边,两人交换位置;接着第2和第3比、第3和第4比……比完10人后,​​最高的人一定站在最右边​​(像气泡浮到水面)
  • ​第2轮​​:同样方式比前9人(最后1人已排好),​​次高的人站到倒数第二​
  • 重复直到全部排好

​Java代码实现​​(含优化:若某轮无交换则提前结束):

public class BubbleSort {
    public static void bubbleSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            boolean swapped = false; // 优化标记
            for (int j = 0; j < n - i - 1; 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 main(String[] args) {
        int[] heights = {160, 155, 175, 170, 165};
        bubbleSort(heights); // 排序后:155, 160, 165, 170, 175
    }
}

​关键特性​​:

  • ⏱️ ​​时间复杂度​​:平均O(n²),最好O(n)(已有序时)
  • 📦 ​​空间复杂度​​:O(1)(原地排序)
  • ⚖️ ​​稳定性​​:相等元素不交换 → ​​稳定排序​
  • 🔧 ​​适用场景​​:小规模数据或基本有序的序列

🔍 ​​二、选择排序:老师点名,最矮的出列​

​体育课故事​​:老师换了一种排队方式:

  • ​第1轮​​:老师扫视全部10人,找到​​最矮的同学​​,让他和队首交换
  • ​第2轮​​:在剩余9人中找​​最矮的​​,让他和第二个位置交换
  • 重复直到全部排好

​Java代码实现​​:

public class SelectionSort {
    public static void selectionSort(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n - 1; i++) {
            int minIndex = i; // 假设当前位置是最矮的
            for (int j = i + 1; j < n; j++) {
                if (arr[j] < arr[minIndex]) {
                    minIndex = j; // 找到更矮的,更新索引
                }
            }
            // 将最小元素交换到当前位置
            int temp = arr[minIndex];
            arr[minIndex] = arr[i];
            arr[i] = temp;
        }
    }
    
    public static void main(String[] args) {
        int[] heights = {160, 155, 175, 170, 165};
        selectionSort(heights); // 排序后:155, 160, 165, 170, 175
    }
}

​关键特性​​:

  • ⏱️ ​​时间复杂度​​:固定O(n²)(无论数据是否有序)

  • 📦 ​​空间复杂度​​:O(1)(原地排序)

  • ⚠️ ​​稳定性​​:交换可能破坏相等元素顺序 → ​​不稳定排序​

    例:[5a, 2, 5b] → 第一轮交换后:[2, 5a, 5b] → 5a5b顺序变了

  • 🔧 ​​适用场景​​:数据量小且​​交换成本较高​​的场景(如磁盘存储)


🃏 ​​三、插入排序:扑克牌式插入,新牌找位置​

​体育课故事​​:老师让学生逐个入队:

  • ​第1步​​:第1个同学直接站好(已排序区:[155]

  • ​第2步​​:第2个同学(160)和155比 → 160>155 → 站155右边 → [155, 160]

  • ​第3步​​:第3个同学(175)比160高 → 站160右边 → [155,160,175]

  • ​第4步​​:第4个同学(170)从右向左比:

    • 170 < 175?→ 175向右挪 → [155,160,空,175]
    • 170 > 160?→ 站160右边 → [155,160,170,175]

​Java代码实现​​:

public class InsertionSort {
    public static void insertionSort(int[] arr) {
        int n = arr.length;
        for (int i = 1; i < n; i++) { // 从第2个元素开始
            int key = arr[i]; // 当前要插入的元素
            int j = i - 1;
            // 向左找插入位置,比key大的右移
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j]; // 大元素右移
                j--;
            }
            arr[j + 1] = key; // 插入到正确位置
        }
    }
    
    public static void main(String[] args) {
        int[] heights = {160, 155, 175, 170, 165};
        insertionSort(heights); // 排序后:155, 160, 165, 170, 175
    }
}

​关键特性​​ :

  • ⏱️ ​​时间复杂度​​:平均O(n²),最好O(n)(已有序时)
  • 📦 ​​空间复杂度​​:O(1)(原地排序)
  • ⚖️ ​​稳定性​​:相等时不后移 → ​​稳定排序​
  • 🔧 ​​适用场景​​:​​基本有序的小数据​​或​​链表结构​​(插入成本低)

📊 ​​终极总结:三大排序算法对比​

​特性​冒泡排序选择排序插入排序
​时间复杂度​O(n²)O(n²)O(n²)
​最好情况​O(n)(优化后)O(n²)O(n)(已有序)
​空间复杂度​O(1)O(1)O(1)
​稳定性​✅ 稳定❌ 不稳定✅ 稳定
​交换次数​多(相邻交换)少(每轮1次)中(移动插入)
​适用场景​小数据、教学用途交换成本高的场景基本有序的小数据

⚡ ​​一句话选型建议​​:

  • 数据量小且要稳定 → ​​插入排序​
  • 数据量小但交换成本高 → ​​选择排序​
  • 数据基本有序 → ​​冒泡排序(优化版)​
  • 数据量大?请用 ​​快速排序​​(O(n log n))4

💡 ​​思考题(检验理解)​

int[] data = {5, 2, 9, 1, 5, 6};
  1. 用​​插入排序​​处理时,当key=第二个5时,是否会移动前一个5
    → ​​不会​​(稳定性:相等不后移)

  2. 用​​选择排序​​处理时,两个5的顺序是否会变?
    → ​​可能变​​(若后面的5被选为最小元素)

  3. 用​​冒泡排序​​优化版,需要几轮完成排序?
    → 实际3轮(第4轮无交换提前结束)

​记住​​:算法没有绝对好坏,​​理解场景才能选出最佳方案!​​ 🌟