插入排序(Insertion Sort)是一种简单直观的排序算法,它的工作原理类似于扑克牌的整理过程。在摸牌时,玩家会将每张新摸到的牌插入到手中已有的有序牌中的合适位置。
1. 算法步骤
- 初始状态:将数组分为已排序和未排序两部分。初始时,数组的第一个元素被认为是已排序部分,其余元素是未排序部分。
- 处理未排序元素:
- 从数组的第二个元素开始,依次取出未排序部分的元素。
- 将取出的元素与已排序部分的元素从后往前进行比较。
- 在比较过程中,若已排序元素大于取出的元素,就将该已排序元素向后移动一个位置。
- 当遇到一个已排序元素小于或等于取出的元素,或者已比较到已排序部分的最前端时,将取出的元素插入到该位置之后。
- 重复过程:重复上述步骤,直到未排序部分没有元素,此时整个数组就已排好序。
2. 代码实现
以下是Python实现插入排序的代码:
def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
while j >= 0 and arr[j] > key:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
return arr
3. 算法分析
- 时间复杂度:
- 最坏情况:数组完全逆序,此时对于每一个未排序元素,都需要与已排序部分的所有元素进行比较并移动位置。第
i
个元素最多需要比较i
次,总的比较次数为 \(1 + 2 + \cdots + (n - 1) = \frac{n(n - 1)}{2}\),时间复杂度为 \(O(n^2)\)。 - 最好情况:数组已经有序,每个元素只需与已排序部分的最后一个元素比较一次,不需要移动位置,时间复杂度为 \(O(n)\)。
- 平均情况:时间复杂度也是 \(O(n^2)\)。
- 最坏情况:数组完全逆序,此时对于每一个未排序元素,都需要与已排序部分的所有元素进行比较并移动位置。第
- 空间复杂度:插入排序只需要几个额外的变量来辅助排序,空间复杂度为 \(O(1)\)。
- 稳定性:插入排序是稳定的排序算法。在比较和插入过程中,相等元素的相对顺序不会改变。例如,在数组
[2, 2*, 1]
中,两个2
的相对顺序在排序后依然保持不变。