1、循环不变式
以插入排序来述说算法基础,以下伪代码
INSERTION-SORT(A)
for j = 2 to A.length
key = A[j]
i = j - 1
whild i > 0 and A[i] > key
A[i + 1] = A[i]
i = i - 1
A[i + 1] = key
算法导论中有循环不变式的概念:在for循环(循环变量为j)的每次迭代的开始,包含元素A[i..j-1]的字数构成了当前排序好的左边部分,剩余的子数组A[j+1..n]对应于扔在右边。事实上,元素A[1..j-1]就是原来位置1到j-1的元素,但是已经按顺序排列。我们把A[i..j-1]的这些性质形式地表示为一个循环不变式。
循环不变式主要用来帮助我们理解算法的正确性。关于循环不变式,我们必须证明三条性质:
初始化:循环的第一次迭代之前,它为真。
保持:如果循环的某次迭代之前他为真,那么下次迭代之前它仍为真。
终止:在循环终止时,不变式为我们提供一个有用的性质,改性质有助于证明算法是否正确
插入排序算法分析,见算法导论第14页
2、分治法
有许多算法在结构上是递归的,为了解决一个给定的问题,算法会递归分解成若干子问题。这些算法典型的准讯分治法的思想:将原问题分解成几个规模较小但类似原问题的子问题,递归地求解这些子问题,然后在合并这些子问题的解来建立原问题的解。
分治模式在每层递归时都有三个步骤:
分解原问题为若干子问题,这些子问题是原问题的规模较小的实例。
解决这些子问题,递归地求解各子问题。然而,若子问题的规模足够小,则直接求解。
合并这些子问题的解成原问题的解。
以下用归并排序算法表现分治法:
MERGE(A, p, q, r)
n1 = q - p + 1
n2 = r - q
let L[1..n1 + 1] and R[1..n2 + 1] be new arrays
for i = 1 to n1
L[i] = A[p + i - 1]
for j = 1 to n2
R[j] = A[q + j]
L[n1 + 1] = ∞
L[n2 + 1] = ∞
i = 1
j = 1
for k = p to r
if L[i] <= R[j]
A[k] = L[i]
i = i + 1
else
A[k] = R[j]
j = j + 1
MERGE-SORT(A, p, r)
if p < r
q = floor((p + r) / 2)
MERGE-SORT(A, p, q)
MERGE-SORT(A, q + 1, r)
MERGE(A, p, q, r)
在MERGE-SORT函数中,把A分解成若干的子数组,然后在调用MERGE把字数组排序,合并。
归并排序算法分析,见算法导论第20页