一、基本原理
- 概念
- 插入排序的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。可以类比为人们整理手中的扑克牌,每次拿到一张新牌,就将它插入到已经排好序的牌中的合适位置。
- 算法步骤
- 从第一个元素开始,该元素可以认为已经被排序。
- 取出下一个元素,在已经排序的元素序列中从后向前扫描。
- 如果该元素(已排序)大于新元素,将该元素移到下一位置。
- 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置。
- 将新元素插入到该位置后。
- 重复步骤2 - 5,直到所有元素都插入到有序序列中。
二、时间复杂度
- 最好情况
- 当待排序的序列本身就是有序的时候,插入排序的时间复杂度为\(O(n)\)。这是因为在这种情况下,每次插入新元素时,只需要比较一次就可以确定它的位置,总共需要比较\(n - 1\)次(假设序列有\(n\)个元素)。例如,序列[1, 2, 3, 4, 5],在插入排序过程中,每个元素都只需要比较一次就可以确定其正确位置。
- 最坏情况
- 当待排序的序列是逆序的时候,时间复杂度为\(O(n^2)\)。例如,对于序列[5, 4, 3, 2, 1],第一个元素插入时不需要比较,第二个元素插入时需要比较1次,第三个元素插入时需要比较2次,以此类推,总的比较次数为\(1 + 2+3+\cdots+(n - 1)=\frac{n(n - 1)}{2}\),所以时间复杂度为\(O(n^2)\)。
- 平均情况
- 平均时间复杂度也是\(O(n^2)\)。在平均情况下,插入一个元素需要比较和移动大约\(n/2\)次,对于\(n\)个元素,总共需要大约\(n^2/4\)次操作,所以时间复杂度为\(O(n^2)\)。
三、空间复杂度
- 插入排序是一种原地排序算法,它只需要\(O(1)\)的额外空间。这是因为在排序过程中,它只需要有限的几个变量来辅助完成排序,如用于比较和交换元素的临时变量,不需要额外的大量存储空间来复制或存储数据。
四、稳定性
- 插入排序是稳定的排序算法。所谓稳定性,是指如果在排序前两个元素相等,那么在排序后它们的相对位置不变。例如,有一个序列[(3, a), (3, b)],其中括号内第一个元素是数值,第二个元素是标记。在插入排序过程中,当比较到两个3时,因为插入排序是从后向前扫描已排序序列,会将新元素插入到合适位置,不会改变两个3的相对顺序,所以插入排序是稳定的。
五、代码实现(以Python为例)
def insertion_sort(arr):for i in range(1, len(arr)):current_value = arr[i]position = iwhile position > 0 and arr[position - 1] > current_value:arr[position] = arr[position - 1]position -= 1arr[position] = current_valuereturn arr
- 在上述代码中,
for
循环从第二个元素(索引为1)开始遍历数组arr
。current_value
存储当前要插入的元素,position
记录当前元素应该插入的位置。while
循环用于在已排序的部分中找到合适的插入位置,将比current_value
大的元素向后移动,最后将current_value
插入到合适的位置。
六、适用场景
- 插入排序适用于数据量较小或者基本有序的序列。当数据量较小的时候,它的简单性使得它能够快速地完成排序任务,并且它对基本有序的序列非常高效,因为它不需要进行太多的比较和移动操作。例如,在一些实时数据处理场景中,新数据不断到来,并且数据大致上是有序的,插入排序可以很好地用于对这些新数据进行排序。