插入排序

算法思想

插入排序(Insertion Sort)的基本思想是:将一个待排序的记录,按其关键字大小插入到前面已排好序的子序列中,直到全部记录插入完成。

  • 核心思想:通过构建有序序列,对未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
  • 操作过程
    1. 初始时,第一个元素被认为是已排好序的子序列。
    2. 从第二个元素开始,依次取出每个元素。
    3. 将取出的元素与已排好序的子序列中的元素从后向前进行比较。
    4. 如果比待插入元素大的元素,则向后移动一位,直到找到待插入元素的正确位置。
    5. 将待插入元素插入到该位置。
    6. 重复上述步骤,直到所有元素都插入到正确的位置。

直接插入排序

算法思想

直接插入排序(Straight Insertion Sort)是一种最简单的插入排序方法。

  • 基本步骤
    1. 假设前 个元素已经排好序。
    2. 将第 个元素(待插入元素)插入到前 个有序元素中,使其成为前 个有序元素的一部分。
    3. 具体做法是:从 元素开始,依次与待插入元素比较。如果当前元素大于待插入元素,则将当前元素后移一位;直到找到第一个小于或等于待插入元素的元素,将待插入元素插入到该元素之后(或之前)。

效率分析

  • 时间复杂度
    • 最好情况:当序列已经有序时,每个元素只需与前一个元素比较一次,不需要移动。时间复杂度为
    • 最坏情况:当序列完全逆序时,每个元素都需要与其前面所有元素比较并移动。时间复杂度为
    • 平均情况:时间复杂度为
  • 空间复杂度(只需要一个额外的空间存储待插入元素)。
  • 稳定性稳定。因为在插入过程中,如果遇到与待插入元素相等的元素,可以选择将其插入到相等元素的后面,从而保持了原有相对次序。

适用性

  • 优点:算法简单,易于实现;对于基本有序的序列效率高。
  • 缺点:对于大规模无序数据,效率较低,比较和移动次数较多。
  • 适用场景:适用于待排序序列数据量较小基本有序的情况。

折半插入排序

算法思想

折半插入排序(Binary Insertion Sort),又称二分插入排序,是对直接插入排序的改进。

  • 改进点:在寻找待插入元素的位置时,不再是顺序查找,而是采用二分查找(折半查找)来确定插入位置。
  • 基本步骤
    1. 假设前 个元素已经排好序。
    2. 对于第 个元素(待插入元素),在已排好序的前 个元素中,使用二分查找找到其应该插入的位置。
    3. 找到位置后,将该位置及之后的所有元素向后移动一位,腾出空间。
    4. 将待插入元素放入腾出的位置。
  • 注意:折半查找只是减少了比较的次数,而元素的移动次数并没有减少。

效率分析

  • 时间复杂度
    • 比较次数:由于采用了二分查找,比较次数显著减少,为
    • 移动次数:与直接插入排序相同,最坏情况下仍为
    • 总时间复杂度:受移动次数影响,仍为
  • 空间复杂度
  • 稳定性稳定

适用性

  • 优点:减少了比较次数,对于比较操作开销较大的数据类型有一定优势。
  • 缺点:元素的移动次数没有减少,因此整体时间复杂度仍然是
  • 适用场景:与直接插入排序类似,适用于数据量较小的序列,但当比较操作的耗时远大于移动操作时,其优势更为明显。

希尔排序

算法思想

希尔排序(Shell Sort),又称“缩小增量排序”,是直接插入排序的一种更高效的改进版本。

  • 核心思想
    1. 分组:将待排序序列划分为若干个子序列,每个子序列由相距某个“增量”(gap)的元素组成。
    2. 组内插入排序:对每个子序列进行直接插入排序。
    3. 缩小增量:逐步减小增量,重复上述分组和组内插入排序的过程。
    4. 最后一次:当增量减小到 1 时,整个序列变为一个子序列,进行最后一次直接插入排序。此时,整个序列已经基本有序,直接插入排序的效率会很高。
  • 增量序列的选择:希尔排序的关键在于增量序列的选择。常见的增量序列有:
    • (初始增量为 ,每次减半)
    • Knuth 序列:

组内直接插入排序

选取下一个组

最后一轮所有数进行直接插入排序

效率分析

  • 时间复杂度:希尔排序的时间复杂度与增量序列的选择有关,目前没有精确的数学表达式。
    • 最好情况
    • 最坏情况
    • 平均情况:一般认为在 之间,比 快,但比 慢。
  • 空间复杂度
  • 稳定性不稳定。因为在不同的子序列中,相同关键字的元素的相对位置可能会发生改变。例如,当增量较大时,相等的元素可能被分到不同的子序列中进行比较和交换,导致相对次序改变。

适用性

  • 优点
    • 比直接插入排序快得多,尤其对于大规模数据。
    • 由于其不稳定性,在某些不要求稳定性的场景下,可以作为快速排序的替代方案。
    • 是少数几个能和 算法媲美的 类算法。
  • 缺点:算法实现相对复杂,增量序列的选择没有统一标准,对稳定性有要求时不能使用。
  • 适用场景:适用于中等规模数据的排序,且不要求稳定性的场景。