插入排序讲解

一、问题背景:我为什么会研究插入排序?

昨天写完冒泡排序,我突然想到:排序的"亲兄弟"其实有一个叫插入排序。

我最早学它的时候,觉得它比冒泡更自然,因为它跟我们平时 整理扑克牌 的方式几乎一模一样。

比如打牌时,我们一张一张把牌插到已经排好序的牌堆里,这不就是插入排序的核心思想吗?

当时刚学的时候,我老觉得冒泡像是"傻力气" ------ 不断交换,而插入排序更像是"聪明点的做法",有点策略。


二、插入排序到底是什么?

一句话总结:
插入排序就是把数组分成"已排序区"和"未排序区",每次从未排序区取一个数,插到已排序区的合适位置。

比方说你在打牌:

  • 起手拿一张牌 → 这时候它自己就是"有序的"。
  • 再摸一张牌 → 你会把它插到前一张的前面或后面,保持顺序。
  • 再摸第三张 → 你会找个合适的位置把它插进去。
  • 最后所有的牌都是有序的。

三、算法过程(举个例子)

假设要排序 [5, 3, 8, 4, 2]

  1. [5] → 第一个元素自然有序。
  2. 插入 3 → [3, 5]
  3. 插入 8 → [3, 5, 8]
  4. 插入 4 → [3, 4, 5, 8]
  5. 插入 2 → [2, 3, 4, 5, 8]

就这样,数组就排好序了。


四、Java 代码实现

我用 Java 写一个最基础版本:

java 复制代码
public class InsertionSort {
    public static void insertionSort(int[] arr) {
        int n = arr.length;
        for (int i = 1; i < n; i++) {  
            // 当前待插入的元素
            int key = arr[i];  
            int j = i - 1;

            // 从已排序区从后往前找合适位置
            while (j >= 0 && arr[j] > key) {
                arr[j + 1] = arr[j];  // 向后挪位置
                j--;
            }
            arr[j + 1] = key;  // 插入到正确位置
        }
    }

    public static void main(String[] args) {
        int[] arr = {5, 3, 8, 4, 2};
        insertionSort(arr);

        // 打印结果
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

运行结果:

复制代码
2 3 4 5 8

五、时间复杂度 & 空间复杂度

八股来了 🤓:

  • 最好情况(数组本来有序):O(n) ------ 因为只需比较,不需要移动。
  • 最坏情况(数组完全逆序):O(n²) ------ 每次插入都要移动所有已排序元素。
  • 平均情况:O(n²)。
  • 空间复杂度:O(1),原地排序。
  • 稳定性:插入排序是稳定的,因为相等元素不会被交换顺序。

六、面试八股模拟 Q&A

我帮你模拟一下可能的面试场景:

Q1:插入排序的思想是什么?

A1:维护一个有序区和无序区,每次从无序区取一个数,插入到有序区的合适位置。

Q2:插入排序的时间复杂度?

A2:最好 O(n),最坏 O(n²),平均 O(n²),空间复杂度 O(1)。

Q3:插入排序稳定吗?

A3:是的,插入排序是稳定的。

Q4:和冒泡排序的区别?

A4:冒泡是通过不断交换相邻元素实现排序,而插入排序是通过移动元素找到合适位置再插入。插入排序通常交换次数更少,更接近我们手工整理数据的思维方式。

Q5:插入排序适合什么场景?

A5:适合 数据量小基本有序 的场景。比如给小数组排序,或者用在更高级排序算法(如希尔排序)的子过程。


七、个人感悟

我第一次写插入排序的时候,写成了"先交换再比较",结果调了半天 bug,后来才意识到 关键在于"挪动"而不是"交换"

这也让我体会到:虽然冒泡和插入的复杂度都一样,但思想差别很大。

另外,很多大厂面试时会问:"如果数组基本有序,你会选什么排序?"

这个时候答"插入排序"是个加分项,因为它在这种情况下能接近 O(n)。

相关推荐
cur1es1 小时前
数据结构Java--8
java·数据结构·算法·散列表
tainshuai1 小时前
朴素贝叶斯:用 “概率思维” 解决分类问题的经典算法
算法·分类·数据挖掘
Y200309163 小时前
支持向量机核心知识总结
算法·机器学习·支持向量机
1白天的黑夜13 小时前
链表-25.k个一组翻转链表-力扣(LeetCode)
数据结构·leetcode·链表
zl_dfq3 小时前
数据结构之 【红黑树的简介与插入问题的实现】
数据结构
CoovallyAIHub4 小时前
应对不平衡数据集:MixUp、CutMix与Focal Loss实战指南
深度学习·算法·计算机视觉
NAGNIP4 小时前
一文理解提示微调(Prefix Tuning/Prompt Tuning/P Tuning)
算法
薛定谔的算法5 小时前
深入探索 ES6 中的 Map 数据结构
前端·javascript·算法