在日常生活中,我们整理扑克牌时,通常会将新摸到的牌插入到手中已有牌的正确位置,使手中的牌始终保持有序。这种”逐个插入到有序部分”的思路,正是插入排序算法的核心思想。

插入排序的基本思路

插入排序(Insertion Sort)是一种简单直观的排序算法。它的工作原理是:将数组中的元素逐个插入到已排序的子数组中,最终使整个数组达到有序状态。具体步骤如下:

  1. 初始状态:默认数组的第一个元素已经是”有序的”(只有一个元素的数组自然有序)。
  2. 逐个处理后续元素:从数组的第二个元素(索引1)开始,将每个元素视为”待插入元素”。
  3. 寻找插入位置:将待插入元素与已排序子数组中的元素从后往前比较,找到合适的位置后插入,确保插入后子数组仍然有序。
  4. 重复过程:直到所有元素都被插入到正确位置,排序完成。

算法实现步骤

以数组 [5, 2, 9, 1, 5, 6] 为例,详细说明插入排序的过程:

  1. 外层循环:从第二个元素(索引1)开始遍历数组,每次取出待插入元素 temp = arr[i]
  2. 内层循环:从当前元素的前一个位置(j = i-1)开始,与 temp 比较:
    - 如果已排序子数组中的元素 arr[j] > temp,则将 arr[j] 后移一位(arr[j+1] = arr[j])。
    - 继续向前比较(j -= 1),直到找到 arr[j] <= tempj < 0(所有元素都比 temp 大)。
  3. 插入元素:将 temp 插入到 j+1 的位置(确保插入后子数组有序)。

Python代码实现

def insertion_sort(arr):
    # 外层循环:从第二个元素开始(索引1)
    for i in range(1, len(arr)):
        temp = arr[i]  # 保存当前待插入的元素
        j = i - 1      # 从已排序子数组的末尾开始比较

        # 内层循环:寻找插入位置,同时后移元素
        while j >= 0 and arr[j] > temp:
            arr[j + 1] = arr[j]  # 当前元素后移一位
            j -= 1               # 继续比较前一个元素

        arr[j + 1] = temp  # 插入temp到正确位置
    return arr

# 测试代码
if __name__ == "__main__":
    test_arr = [5, 2, 9, 1, 5, 6]
    print("排序前:", test_arr)
    sorted_arr = insertion_sort(test_arr)
    print("排序后:", sorted_arr)

代码执行示例

[5, 2, 9, 1, 5, 6] 为例,逐步拆解排序过程:

  1. i=1(待插入元素=2)
    - temp=2j=0arr[0]=5>2arr[1]=5(数组变为 [5,5,9,1,5,6]),j=-1
    - 插入 tempj+1=0 → 数组变为 [2,5,9,1,5,6]

  2. i=2(待插入元素=9)
    - temp=9j=1arr[1]=5<=9 → 循环终止,插入位置 j+1=2,数组不变。

  3. i=3(待插入元素=1)
    - temp=1j=2arr[2]=9>1arr[3]=9(数组变为 [2,5,9,9,5,6]),j=1
    - arr[1]=5>1arr[2]=5(数组变为 [2,5,5,9,5,6]),j=0
    - arr[0]=2>1arr[1]=2(数组变为 [2,2,5,9,5,6]),j=-1
    - 插入 tempj+1=0 → 数组变为 [1,2,5,9,5,6]

  4. 后续步骤:继续处理剩余元素(5和6),最终数组变为 [1,2,5,5,6,9]

复杂度分析

  • 时间复杂度
  • 最好情况(数组已排序):O(n)(每个元素只需比较一次)。
  • 最坏情况(数组逆序):O(n²)(每个元素需比较n次)。
  • 空间复杂度:O(1)(仅需一个临时变量temp,原地排序)。

插入排序适用于小规模数据或基本有序的数据,实现简单且稳定。通过理解”逐个插入”的核心思想,你能轻松掌握这一经典排序算法的实现逻辑。

小夜