DeepSeek 插入排序

好的,我们来详细讲解一下插入排序。

插入排序是一种简单直观的排序算法,它的工作原理非常类似于我们整理手中的扑克牌。

核心思想

将待排序的序列(数组)看作两部分:

  1. 已排序序列:默认第一个元素自身就是有序的。
  2. 未排序序列:第一个元素之后的所有元素。

排序过程中,逐个地将未排序序列中的元素插入到已排序序列中的正确位置,直到所有元素都插入完毕。


算法步骤

  1. 开始:从数组的第二个元素开始(索引为1,因为第一个元素默认已排序),将其视为"待插入元素"。
  2. 比较与移动:
    · 将"待插入元素"与它前面的已排序序列中的元素从后往前依次比较。
    · 如果前面的元素比"待插入元素"大,则将该元素向后移动一位,为"待插入元素"腾出空间。
    · 继续向前比较,直到找到一个比"待插入元素"小或相等的元素,或者已经比较到数组的开头。
  3. 插入:将"待插入元素"插入到找到的正确位置(即最后一个被移动的元素的原位置)。
  4. 重复:对下一个未排序元素(即索引为2, 3, ...的元素)重复步骤2和3,直到整个数组排序完成。

图解示例

假设我们要对数组 [5, 2, 4, 6, 1, 3] 进行升序排序。

· 初始状态:[5, 2, 4, 6, 1, 3]

· 5 是初始的已排序序列。

· 2, 4, 6, 1, 3 是未排序序列。

  1. 第一轮 (i=1):处理元素 2
    · 比较:2 < 5,将 5 向后移动 → [5, 5, 4, 6, 1, 3]
    · 到达头部,插入 2 → [2, 5, 4, 6, 1, 3]
  2. 第二轮 (i=2):处理元素 4
    · 比较:4 < 5,将 5 向后移动 → [2, 5, 5, 6, 1, 3]
    · 比较:4 > 2,在 2 后面插入 4 → [2, 4, 5, 6, 1, 3]
  3. 第三轮 (i=3):处理元素 6
    · 比较:6 > 5,无需移动,直接插入当前位置 → [2, 4, 5, 6, 1, 3]
  4. 第四轮 (i=4):处理元素 1
    · 比较:1 < 6,移动 6 → [2, 4, 5, 6, 6, 3]
    · 比较:1 < 5,移动 5 → [2, 4, 5, 5, 6, 3]
    · 比较:1 < 4,移动 4 → [2, 4, 4, 5, 6, 3]
    · 比较:1 < 2,移动 2 → [2, 2, 4, 5, 6, 3]
    · 到达头部,插入 1 → [1, 2, 4, 5, 6, 3]
  5. 第五轮 (i=5):处理元素 3
    · 比较:3 < 6,移动 6 → [1, 2, 4, 5, 6, 6]
    · 比较:3 < 5,移动 5 → [1, 2, 4, 5, 5, 6]
    · 比较:3 < 4,移动 4 → [1, 2, 4, 4, 5, 6]
    · 比较:3 > 2,在 2 后面插入 3 → [1, 2, 3, 4, 5, 6]

排序完成!


代码实现(Python)

python 复制代码
def insertion_sort(arr):
    """
    对数组进行插入排序 (升序)
    """
    # 遍历从1到n-1,因为第一个元素默认已排序
    for i in range(1, len(arr)):
        key = arr[i]  # 当前待插入的元素
        j = i - 1     # 从i的前一个位置开始比较

        # 将比key大的元素都向后移动一位
        while j >= 0 and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        
        # 将key插入到找到的正确位置
        arr[j + 1] = key

# 测试代码
if __name__ == "__main__":
    my_list = [5, 2, 4, 6, 1, 3]
    print("原始数组:", my_list)
    insertion_sort(my_list)
    print("排序后数组:", my_list)

输出:

复制代码
原始数组: [5, 2, 4, 6, 1, 3]
排序后数组: [1, 2, 3, 4, 5, 6]

算法分析

· 时间复杂度:

· 最坏情况:数组完全逆序。每个新元素都需要比较并移动到最前面。需要进行 1 + 2 + 3 + ... + (n-1) = n(n-1)/2 次比较和移动,即 O(n²)。

· 最好情况:数组已经有序。每个新元素只需要比较一次。需要进行 (n-1) 次比较,0次移动,即 O(n)。

· 平均情况:O(n²)。

· 空间复杂度:O(1)。因为它是一种原地排序算法,只使用了常数级别的额外空间(用于存储 key 和索引)。

· 稳定性:稳定。在比较时,如果遇到相等的元素,插入排序会将新元素放在相等元素的后面,不会改变它们的相对顺序。


优缺点

优点:

· 实现简单,代码易于理解和编写。

· 对于小规模数据或基本有序的数据,效率很高。

· 是稳定的排序算法。

· 是原地排序算法,空间效率高。

· 在线算法:可以逐个接收数据并进行排序,适用于数据流。

缺点:

· 对于大规模乱序数据,效率较低,时间复杂度为 O(n²)。

总结

插入排序是一种基础且重要的排序算法。虽然它在处理大数据时不如快速排序、归并排序等高效算法,但由于其实现简单、对小数据集和近乎有序的数据集效率很高,它在实际中仍有广泛应用,例如作为快速排序等复杂算法在小规模数据上的优化子过程。理解插入排序是学习更高级排序算法的重要基础。

相关推荐
DanyHope几秒前
LeetCode 两数之和:从 O (n²) 到 O (n),空间换时间的经典实践
前端·javascript·算法·leetcode·职场和发展
Destiny_where7 分钟前
k8s常用指令集合
linux·docker·kubernetes
free-elcmacom7 分钟前
机器学习高阶教程<6>推荐系统高阶修炼手册:混排、多任务与在线学习,解锁精准推荐新境界
人工智能·python·学习·算法·机器学习·机器人
yuniko-n8 分钟前
【MySQL】通俗易懂的 MVCC 与事务
数据库·后端·sql·mysql
断剑zou天涯8 分钟前
【算法笔记】AC自动机
java·笔记·算法
诸神黄昏EX9 分钟前
Android Qualcomm USB 专题系列【总篇:USB HAL架构】
android·linux·网络
IT猿手11 分钟前
基于粒子群算法与动态窗口混合的无人机三维动态避障路径规划研究,MATLAB代码
算法·matlab·无人机·多目标优化算法·多目标算法
民乐团扒谱机12 分钟前
【微实验】仿AU音频编辑器开发实践:从零构建音频可视化工具
算法·c#·仿真·audio·fft·频谱
今天过得怎么样14 分钟前
彻底搞懂 Spring Boot 中 properties 和 YAML 的区别
后端
DanyHope15 分钟前
LeetCode 283. 移动零:双指针双解法(原地交换 + 覆盖补零)全解析
数据结构·算法·leetcode