2、算法导论笔记

来源:互联网 发布:淘宝课堂网址 编辑:程序博客网 时间:2024/05/18 00:17

2、算法导论笔记 - 插入排序

排序问题

排序问题的形式定义如下:

Input: A sequence of n numbers a1,a2,,an.Output: A permutation (reordering) a1,a2,,an of the input such that a1a2an

待排序的元素称为

插入排序

插入排序对于少量元素很有效。它的原理类似于打扑克时牌手摸牌的方式:开始时,牌手左手为空,所有牌牌面向下放在牌桌上,牌手每次从桌上摸一张牌,并插入到左手正确的位置中。寻找正确位置的方法是:将摸到的牌从右向左,依次和手中的牌进行比较。无论何时,左手中的牌都是排好序的。

这里使用过程INSERTION-SORT表示插入排序的伪码。它以一个拥有n个元素的数组A[1..n]作为输入。插入排序算法是原地排序的,算法在数组内排序元素,就是说,就是说,在任意时刻,最多只有常数个元素保存在数组之外。

插入排序伪码及实现

插入排序伪码:

INSERTIONSORT(A)1 for j=2 to A.length2key=A[j]3//insert A[j] into the sorted sequence A[1..j1]4i=j15while i>0 and A[i]<key6A[i+1]=A[i]7i=i18A[i+1]=key

插入排序Python实现:

def insertion_sort(seq):    """    插入排序    :param seq: 待排数组    :return: seq    """    length = len(seq)    for i in range(1, length):        key = seq[i]        j = i - 1        while j >= 0 and seq[j] > key:            seq[j + 1] = seq[j]            j -= 1        seq[j + 1] = key    return seq

循环不变式以及算法正确性

这里以数组A=5,2,4,6,1,3为例,下图展示了插入排序是如何工作的:
insert-sort.png-19.7kB

索引j表示的是待插入的“当前牌”。在每次for循环迭代之前,子数组A[1..j1]中的元素都是排好序的,此外子数组A[j+1..n]中的元素代表牌桌上的牌。实际上,子数组A[1..j1]中的元素依然在子数组A[1..j1]中,不过是排好序的。我们将这种属性称为循环不变式

循环不变式可以帮助我们理解算法的正确性,共有三种性质:

  • 初始:在每次循环迭代之前算法是正确的。
  • 维持:如果算法在某次迭代开始之前是正确的,那么,在下次迭代开始之前算法也应该是正确的。
  • 终止:迭代结束后,算法给出一个有用的性质。

插入排序算法分析

过程INSERTION-SORT执行所需的时间取决于输入的规模,此外,根据输入的排序程度,过程INSERTION-SORT排序两个同等输入规模的输入也会需要不同时间。这里我们使用一个输入规模的函数表示算法的运行时间。

这里先给出过程INSERTION-SORT中每条语句的时间“代价”和语句的执行次数。使用tj表示伪码中第5行while循环的测试次数。通常,循环的测试要比循环体多执行一次。

INSERTIONSORT(A)1 for j=2 to A.length2key=A[j]3//insert A[j] into the sorted sequence A[1..j1]4i=j15while i>0 and A[i]<key6A[i+1]=A[i]7i=i18A[i+1]=keycostc1c20c4c5c6c7c8timesnn1n1n1j=2ntjj=2n(tj1)j=2n(tj1)n1

算法的运行时间就是每条语句执行时间的总和。设T(n)为排序n个元素的执行时间,有:
T(n)=c1n+c2(n1)+c4(n1)+c5j=2ntj+c6j=2n(tj1)+c7j=2n(tj1)+c8(n1)

即使给定输入规模,算法的运行时间也取决于输入的元素。例如,过程INSERTION-SORT中,最佳情况发生在输入已排好序的时候,此时对所有j=2,3,,n,都有tj=1,因此最佳运行时间为:
T(n)=(c1+c2+c4+c5+c8)n(c2+c4+c5+c8)

可以使用an+b表达式表述此类运行时间,常量ab的值取决于语句的执行代价ci,它是一个线性函数

如果输入数组是倒序的,就会出现最坏情况。有:

j=2nj=n(n+1)21andj=2n(j1)=n(n1)2

最坏情况下算法总的运行时间为:
T(n)=(c52+c62+c72)n2+(c1+c2+c4+c52c62c72+c8)n(c2+c4+c5+c8)

最坏情况下的运行时间可以用an2+bn+c表述,它是n二次函数