算法-插入排序

算 法:插入排序算法 时间复杂度:\(O(n^2)\)

  • 插入排序算法描述
  • 插入排序伪代码
  • 插入排序实现

插入排序算法概述

插入排序的原理是构建有序序列,对于给定的一个无序序列,从前往后遍历,在该元素之前的序列中从后往前扫描,寻找正确位置,这样对于每一个正在排序的元素,前面的序列总是有序的,当遍历完整个序列,即完成排序。《算法导论》给了一个更通俗更容易理解的形象的描述。我们都玩过扑克牌,大多数人拿扑克牌的时候都有这么个习惯,那就是将扑克牌按照一定的顺序排列好,而插入排序就好比你不断从桌上一堆无序排中拿起最上面的那张,然后放入自己手中已有的牌中,而每一次放的过程你都会按照某个顺序将这张新拿到的牌插入正确的位置,这样你手中的牌一直是有序的,而你抽取牌所在的牌堆是无序的。

算法描述

下面以非降序排序为例: 1. 从第一个元素开始,该元素视为已经被排序; 2. 取出下一个元素记为key,在前面已排序的有序序列中从后往前扫描; 3. 如果扫描过程中的元素大于key,将该元素移至下一个位置; 4. 重复3,直至找到已排序的元素小于或等于key的位置; 5. 将key插入到该位置; 6. 重复2-5,直到整个序列遍历完即得到一个原地排序好的序列。

执行过程图解

以斜体数字如 1 表示key,以粗体数字如 ‘1’ 表示已排序序列,为了更直观,用中括号括起来,普通数字如‘1’表示未排序乱序序列,简要表示排序流程如下:

  • 5 2 4 6 1 3
  • [5] 2 4 6 1 3
  • [2 5] 4 6 1 3
  • [2 4 5] 6 1 3
  • [2 4 5 6] 1 3
  • [1 2 4 5 6] 3
  • [1 2 3 4 5 6]

插入排序的动态演示:

VisuAlgo-排序(冒泡排序,选择排序,插入排序,归并排序,快速排序,基数排序,基数排序)

插入排序伪代码

(伪代码引用《算法导论》给出的例子) INSERTION-SORT(A)

1
2
3
4
5
6
7
8
for j = 2 to A.length
key = A[j]
// Insert A[j] into the sorted sequence A[1..j - 1].
i = j - 1
while i > 0 and A[i] > key
A[i + 1] = A[i]
i = i - 1
A[i + 1] = key

插入排序实现

为了更直观,我们将所有元素从1号元素开始计数,将0号元素视为无穷小,即数组长度为arrLength + 1,序列存储于arr[1..arrLength]。 ## C

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void insertionSort(arrType* arr, int arrLength)
{
int i, j;
arrType key;

for (j = 2; j <= arrLength; j++) {
key = arr[j];

i = j - 1;
while (i > 0 && arr[i] > key) {
arr[i + 1] = arr[i];
i--;
}
arr[i + 1] = key;
}
}
## Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
procedure insertsort;   
var
i,j,key:integer;
begin
arr[0] := -maxint;
for j := 2 to n do
begin
i := j - 1;
key := arr[j];
while arr[i] > key do
begin
arr[i + 1] := arr[i];
i := i - 1;
end;
arr[i + 1] := key;
end;
end;
# 参考资料 * 《算法导论》(原书第3版) * 插入排序-维基百科,自由的百科全书 * 《Free Pascal 语言与基础算法》