InsertSort 插入排序

问题

用Insert Sort对长度为nn的无序序列ss从小到大(升序)排序。

解法

将长度为nn的序列s=[x0,x1,,xn1]s = [x_0, x_1, \dots, x_{n-1}]分为左右两个部分,已排序的left=[x0,,xk]left = [x_0, \dots, x_k]和未排序的right=[xk+1,,xn1]right = [x_{k+1}, \dots, x_{n-1}],其中0kn0 \le k \le n。如图:

初始时left=,right=[x0,,xn1]left = \varnothing, right = [x_0, \dots, x_{n-1}]

leftleftrightright进行如下操作:

function Insert(s, k, n):
    let x = s[k+1]
    for i = [0, k+1]
        if i = 0 and x <= s[i]
            break
        if i > 0 and s[i-1] <= x <= s[i]
            break
    if i <= k
        move s[i...k] to s[i+1...k+1]
        let s[i] = x

(1) Insert函数第3-7行:遍历leftleft找出一个适合xx插入的位置s[i]s[i]。其中i=0i = 0属于边界条件,只需判断x<=s[0]x <= s[0]即可;

(2) Insert函数第8-10行:若找到一个合适的插入位置0<=i<=k0 <= i <= k则将其插入;若找不到(i=k+1i = k + 1)则说明xxleftleft中所有元素都大,不需要移动。下次调用Insert函数时输入参数kk变成k+1k + 1,就可以将现在的s[k+1]s[k+1]加入leftleft中;

上述操作如图:

运行一次Insert函数可以将rightright最左边的元素插入到leftleft中合适的位置(leftleft长度减1,rightright长度加1)。初始时leftleft长度为00rightright长度为nn,只需重复调用nn次Insert函数即可完成排序:

function InsertSort(s, n):
    for k = [0, n-2]
        Insert(s, k, n)

例如下图中,leftleft部分为s[0,5]s[0,5]rightright部分为s[6,n1]s[6,n-1]rightright最左边的首部元素x=s[6]=41x = s[6] = 41,在leftleft部分中合适的插入位置为i=3i = 3s[2]xs[3]s[2] \le x \le s[3])。

s[3,5]s[3,5]向右移动一位到s[4,6]s[4,6],将原xx移动到s[3]s[3],就完成了一次插入。

复杂度

与BubbleSort算法类似,该算法的时间复杂度为O(n2)O(n^2),空间复杂度为O(1)O(1)

源码

InsertSort.h

InsertSort.cpp

测试

InsertSortTest.cpp

Last updated