【挑战程序设计竞赛 | 笔记】插入排序:Insertion Sort

48 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 26 天,点击查看活动详情

认识排序

排序就是将数据按一定顺序重新排列,即将数据按照键重新排列为升序( 从小到大 ) 或降序( 从大到小 ) 的处理。

比如:

  • 一个数列为:A = {5, 1, 3, 4, 2}
  • 按升序排列:A = {1, 2, 3, 4, 5}
  • 按降序排列:A = {5, 4, 3, 2, 1}

我们通过数组来管理这些数列形式的数据,并通过循环处理完成数据的交换和移动,最终实现排序。

我们在设计或者选择算法时,不仅需要考虑复杂度,还要考虑该排序算法是否稳定。

稳定排序指的是:当需要排序的数据中存在 2 个或者 2 个以上的相等值时,这些元素在排序前后的顺序不变。

插入排序 | Insertion Sort

思想

举个例子,比如我们拿着手牌在打扑克,需要将牌从左到右,由小到大进行排序。此时我们需要将牌一张张抽出来,分别插入到前面已排好序的手牌中的适当位置。重复这一操作 直到插入最后一张牌,整个排序就完成了。

插入排序就是这样一个思想。

具体的,插入排序算法记录如下:

  1. 首先,插入排序算法将开头元素视为已排序完成

  2. 接着执行以下处理(直到排序完成):

    1. 取出未排序部分的开头元素赋给变量 tmp
    2. 在已排序部分,将所有比 tmp 大的元素向后移动一个单位
    3. 将已取出的元素 tmp 插入空位
    4. 重复以上流程,直到排序结束

代码

插入算法的代码如下:(C++版):

// 包含了 n 个元素的数组 A
void insertionSort(int A[], int n) {
    int i, j, tmp;
    for(i = 1; i < n; i++) {
        tmp = A[i];
        j = i - 1;
        while( j >= 0 && tmp < A[j] ) {
            A[j+1] = A[j];
            j--;
        }
        A[j+1] = tmp;
    }
}

插入排序在整个排序过程中,会将数组分为两个部分:已排序部分未排序部分

在上述 C++ 代码中可以看到:

  • 外层循环的 i 从 1 开始自增。在每次循环开始时,将 A[i] 的值临时保存在变量 tmp中, tmp变量的值就是未排序部分的开头元素。
  • 接着是内部循环。我们要从前面已排序部分中,挨个寻找。将每个比 tmp 大的元素都后移一位,此时一旦遇到一个值比 tmp 小,那么就将tmp存放到该值的后面。
  • 重复以上过程,就能成功排序完毕。

因此,我们说插入排序算法最核心的操作就是:将已排序部分的其中一段向后移动,再把未排序部分的开头元素插入已排序部分的恰当位置。

分析

在插入排序法中:

  • 稳定性:我们只将比 tmp 大的元素向后移动,不相邻的元素不会直接交换位置,因此整个排序算法十分稳定。
  • 时间复杂度:O(n2)O(n^2)

记录:

  • 插入排序算法的优势在于能够快速处理相对有序的数据。