INSERTION_SORT(A)
for j = 2 to A.length
key = A[j]
i = j-1
while i > 0 and A[i] > key
A[i+1] = A[i]
i = i-1
A[i+1] = key
循环不变式为:for循环的每次迭代开始时,子数组A[1…j-1]由原来在A[1…j-1]中的元素组成,但以按序排列。
初始化:对循环技术变量的初始赋值后、在循环头的第一次测试之前,保持循环不变式。
保持:每次迭代保持循环不变式。
终止:循环终止时保持循环不变式。
T = O ( n 2 ) T=O(n^2) T=O(n2)
(1) Θ \Theta Θ记号:渐进紧确界
(2) O O O记号:渐进上界
(3) Ω \Omega Ω记号:渐进下界
例题: T ( n ) = 4 T ( n / 2 ) + n T(n)=4T(n/2)+n T(n)=4T(n/2)+n
猜测: T ( n ) = O ( n 3 ) T(n)=O(n^3) T(n)=O(n3)
假设 T ( k ) ≤ c k 3 T(k)\leq ck^3 T(k)≤ck3,对于 k < n k<n k<n
证明存在 c > 0 c>0 c>0,使得 T ( n ) ≤ c n 3 T(n)\leq cn^3 T(n)≤cn3
证: T ( n ) = 4 T ( n / 2 ) + n ≤ 4 c ( n / 2 ) 3 + n = c n 3 − ( ( c / 2 ) n 3 − n ) ≤ c n 3 T(n)=4T(n/2)+n\leq4c(n/2)^3+n=cn^3-((c/2)n^3-n) \leq cn^3 T(n)=4T(n/2)+n≤4c(n/2)3+n=cn3−((c/2)n3−n)≤cn3
要使 ( c / 2 ) n 3 − n ≥ 0 (c/2)n^3-n\geq0 (c/2)n3−n≥0,有 c ≥ 2 , 且 n ≥ 1 c\geq2,且n\geq1 c≥2,且n≥1
将树中每层中的代价求和,得到每层代价,然后将所有层的代价求和,得到所有层次的递归调用的总代价。书P50
主方法适用于下面的递归形式:
T ( n ) = a T ( n / b ) + f ( n ) , 其 中 a ≥ 1 , 和 b > 1 T(n)=aT(n/b)+f(n),其中a\geq1,和b>1 T(n)=aT(n/b)+f(n),其中a≥1,和b>1是常数, f ( n ) f(n) f(n)是渐进正函数
将 f ( n ) 与 n log b a f(n)与n^{\log_b a} f(n)与nlogba进行比较:
(1) f ( n ) = O ( n log b a − ε ) 即 f ( n ) < n log b a 时 , f ( n ) 比 n log b a 增 长 的 慢 : f(n)=O(n^{\log_b a-\varepsilon})即f(n)<n^{\log_b a}时,f(n)比n^{\log_ba}增长的慢: f(n)=O(nlogba−ε)即f(n)<nlogba时,f(n)比nlogba增长的慢:
T ( n ) = Θ ( n log b a ) T(n)=\Theta(n^{\log_ba}) T(n)=Θ(nlogba)
(2) f ( n ) = Θ ( n log b a ) 即 f ( n ) = n log b a 时 , f ( n ) 和 n log b a lg n 增 长 速 度 相 同 : f(n)=\Theta(n^{\log_ba})即f(n)=n^{\log_ba}时,f(n)和n^{\log_ba} \lg n增长速度相同: f(n)=Θ(nlogba)即f(n)=nlogba时,f(n)和nlogbalgn增长速度相同:
T ( n ) = Θ ( n log b a lg n ) T(n)=\Theta(n^{\log_ba} \lg n) T(n)=Θ(nlogbalgn)
(3) f ( n ) = Ω ( n log b a + ε ) 即 f ( n ) > n log b a 时 , f ( n ) 比 n log b a 增 长 的 快 : f(n)=\Omega(n^{\log_b a+\varepsilon})即f(n)>n^{\log_b a}时,f(n)比n^{\log_ba}增长的快: f(n)=Ω(nlogba+ε)即f(n)>nlogba时,f(n)比nlogba增长的快:
T ( n ) = Θ ( f ( n ) ) T(n)=\Theta(f(n)) T(n)=Θ(f(n))
(1)将问题分解为子问题
(2)递归地求解子问题
(3)组合子问题的答案
举例:
SQUARE-MATRIX-MULTIPLY(A,B)
n=A.rows
let C be a new nXn matrix
for i=1 to n
for j=1 to n
c[i][j] = 0
for k=1 to n
c[i][j] += A[i][k] * B[k][j]
return C
QUICKSORT(A,p,r)
if p<r
q=PARTITION(A,p,r)
QUICKSORT(A,p,q-1)
QUICKSORT(A,q+1,r)
PARTITION(A,p,q)
x=A[p]
i=p
for j=p+1 to q
do if A[j] <= x
then i=i+1
exchange A[i] <-> A[j]
exchange A[p] <-> A[i]
return i
直接调用QUICKSORT(A,1,n)
快速排序期望运行时间: T ( n ) = O ( n lg n ) T(n)=O(n\lg n) T(n)=O(nlgn),最坏情况: T ( n ) = Θ ( n 2 ) T(n)=\Theta(n^2) T(n)=Θ(n2)
PARTITION的时间复杂度 T ( n ) = Θ ( n ) T(n)=\Theta(n) T(n)=Θ(n)
PARTITION循环不变量:对于任意数组下标k,有:
(1) 若 p + 1 ≤ k ≤ i , 则 A [ k ] ≤ x 若p+1\leq k\leq i,则A[k]\leq x 若p+1≤k≤i,则A[k]≤x
(2) 若 i + 1 ≤ k ≤ j − 1 , 则 A [ k ] > x 若i+1\leq k\leq j-1,则A[k]>x 若i+1≤k≤j−1,则A[k]>x
(3) 若 k = p , 则 A [ k ] = x 若k=p,则A[k]=x 若k=p,则A[k]=x
COUNTING-SORT(A,B,k)
for i=1 to k
do C[i] = 0
for j=1 to n
do C[A[j]] = C[A[j]]+1
for i=2 to k
do C[i] = C[i] + C[i-1]
for j=n downto 1
do B[C[A[j]]] = A[j]
C[A[j]] = C[A[j]] - 1
T ( n ) = Θ ( n + k ) T(n)=\Theta(n+k) T(n)=Θ(n+k),计数排序是稳定的排序
RADIX-SORT(A,d)
for i=1 to d
use a stable sort to sort array A on digit i
T ( n ) = Θ ( d ( n + k ) ) , 其 中 d 为 数 字 的 最 高 位 数 T(n)=\Theta(d(n+k)),其中d为数字的最高位数 T(n)=Θ(d(n+k)),其中d为数字的最高位数
二叉搜索树的期望高度为 O ( lg n ) O(\lg n) O(lgn),也为二叉搜索树的搜索时间
遍历有n个结点的二叉搜索树需要 Θ ( n ) \Theta(n) Θ(n)的时间
红黑树的性质:
(1)任何一个结点要么是黑的要么是红的。
(2)根和叶子(NIL)是黑的。
(3)如果一个结点是红的,那么它的父亲是黑的。
(4)从任何一个结点x到它的后代叶子的简单路径上的黑结点的数目是相同的=black-height(x)
一棵有n个键的红黑树高度 h ≤ 2 lg ( n + 1 ) h\leq 2\lg (n+1) h≤2lg(n+1)
SEARCH、MINIMUM、MAXIMUM、SUCCESSOR(后继)、PREDECESSOR(前驱)在红黑树上的时间复杂度 T ( n ) = O ( lg n ) T(n)=O(\lg n) T(n)=O(lgn)
T ( n ) = O ( 1 ) T(n)=O(1) T(n)=O(1)
将15插入树,15为红色
红黑树的插入情况1:直接重新着色
红黑树的插入情况2:左旋转
红黑树的插入情况3:右旋转
O S − S E L E C T ( i , S ) : 查 找 以 S 为 根 的 第 i 小 的 关 键 字 的 结 点 , T ( n ) = O ( lg n ) OS-SELECT(i,S):查找以S为根的第i小的关键字的结点,T(n)=O(\lg n) OS−SELECT(i,S):查找以S为根的第i小的关键字的结点,T(n)=O(lgn)
O S − R A N K ( x , S ) : 返 回 以 S 为 根 的 关 键 字 为 x 的 结 点 的 位 置 , T ( n ) = O ( lg n ) OS-RANK(x,S):返回以S为根的关键字为x的结点的位置,T(n)=O(\lg n) OS−RANK(x,S):返回以S为根的关键字为x的结点的位置,T(n)=O(lgn)
(1)最优子结构
(2)重叠子问题
LCS的递归代码:
LCS(x,y,i,j)
if x[i] = y[j]
then c[i,j] = LCS(x,y,i-1,j-1) + 1
else c[i,j] = max{LCS(x,y,i-1,j),LCS(x,y,i,j-1)}
T ( n ) = O ( m + n ) T(n)=O(m+n) T(n)=O(m+n)
LCS的备忘录代码:
LCS(x,y,i,j)
if c[i,j] = NIL
then if x[i] = y[j]
then c[i,j] = LCS(x,y,i-1,j-1) + 1
else c[i,j] = max{LCS(x,y,i-1,j),LCS(x,y,i,j-1)}
P224
带备忘的自上而下的递归的矩阵链排序: T ( n ) = O ( n 3 ) T(n)=O(n^3) T(n)=O(n3)
MEMOIZED-MATRIX-CHAIN(p)
n = p.length-1
let m[1..n,1..n]be a new table
for i=1 to n
for j=i to n
m[i,j] = ∞
return LOOKUP-CHAIN(m,p,1,n)
LOOKUP-CHAIN(m,p,i,j)
if m[i,j] < ∞
return m[i,j]
if i==j
m[i,j]=0
else for k=i to j-1
q = LOOKUP-CHAIN(m,p,i,k) + LOOKUP-CHAIN(m,p,k+1,j) + p[i-1]*p[k]*p[j]
if q < m[i,j]
m[i,j] = q
return m[i,j]
(1)最优子结构
(2)贪心选择性质
动态表: n个插入的最坏代价 T ( n ) = Θ ( n ) T(n)=\Theta(n) T(n)=Θ(n)
三种常用的平摊分析方法:
(1)聚集法
(2)记账法
(3)势能法
二项堆是由一组满足二项堆性质的二项树组成