6.5-7 Heap-DELETE(A, i)操作结点i中的项从堆A中删去。对含n个元素的最大堆,请给出时间为O(lgn)的HEAP-DELETE的实现。
Heap-DELETE(A, i)
del_val ← A[i]
if i = heap-size[A]
then heap-size[A] ← heap-size - 1
return del_val
HEAP-INCREASE-KEY(A, i, key)
HEAP-EXTRACT-MAX(A)
return del_val
6.5-8 请给出一下时间为O(n*lgk),用来将 k 个已排序链表合并为一个排序链表的算法.此处,n 次所有输入链表中元素的总数.
假设 k 个链表均为非空单向链表,带有头结点,且按递增排序的。数组L[k]存放k个链表的头结点。最终结果存在链表链表R。
LIST-MERGE(L[k])
create arrays A[1..k]
create list R
current ← head[R]
heap-size[A] ← k
for i ← 1 to k
do A[i] ← next[L[i]]
BUILD-MAX-HEAP(A)
while heap-size(A) > 0
do min ← HEAP-MINIMUM(A)
next[current] ← min
current ← min
if next[min] = NULL
then HEAP-EXTRACT-MINIMUM(A)
else
then A[1] ← next[min]
MIN-HEAPIFY(A)
return R
思考题6-3
一个 m*n 的 Young 氏矩阵(Young tableau) 是一个 m*n 的矩阵,其中每一行的数据都从左到右排序,第一列的数据都从上到下排序.Young 氏矩阵中可能会有一些 ∞ 数据项,表示不存在的元素.所以,Young 氏矩阵可以用来存放 r<= mn 个有限的元素.
a).画一个包含{9,16,3,2,4,8,5,14,12} 的4*4 的Young 氏矩阵.
b).给出一个在非空 m*n 的 Young 氏矩阵上实现 EXTRACT-MIN 算法,使其运行时间为O(m+n).
c).说明如何在O(m+n)时间内,将一个新元素手入到一个未满的 m*n Young 氏矩阵中.
d).给出一个时间复杂度为 O(n^3) 的对 n*n Young 氏矩阵排序的算法.
f).给出一个运行时间为O(m+n) 的算法,来决定一个给定的数是否存在于一个给定的 m*n 的 Young 氏矩阵当中.
row[A], col[A]分别为Young矩阵行与列数目。
b)
算法分析
设大小为m*n的Young氏矩阵A[1...m, 1...n],根据Young氏矩阵的性质,矩阵的最小值是为A[1,1]。因为A[2,1]、A[1,2]分别是子矩阵A[1..m-1, 1...n]和A[1...m, 1...n-1]的最小值,所以矩阵A的第二小的值为min(A[2,1],A[1,2])。假设min(A[2,1],A[1,2])= A[1,2],当EXTRACT-MIN(A)把矩阵A的最小值A[1,1]取出时,为保持Young氏矩阵的性质,需把A[1,2]移到 A[1,1]。此移动操作又导致了对子矩阵A[1...m, 1...n-1]进行了EXTRACT-MIN。因此在m*n的Young氏矩阵上实现EXTRACT-MIN的算法,可以使用一个递归的过程,通过解决(m-1)*n或m*(n-1)子问题来解决m*n问题。
伪代码
//Young氏矩阵为A,i,j为子矩阵的左上角的坐标
YOUNG-EXTRACT-MIN(A, i, j)
min ← A[i, j]
A[i, j] ← ∞
if i < m and j < n
then if A[i+1, j] < A[i, j+1]
then exchange(A[i, j], A[i+1, j])
EXTRACT-MIN(A, i+1, j)
else
exchange(A[i, j], A[i, j+1])
EXTRACT-MIN(A, i, j+1)
else if i < m and j = n
then exchange(A[i, j], A[i+1, j])
EXTRACT-MIN(A, i+1, j)
else if i = m and j < n
then exchange(A[i, j], A[i, j+1])
EXTRACT-MIN(A, i, j+1)
else // i = m and j =n
return min;
算法复杂度分析:
m.n 分别为矩阵的行数与列数,P = m + n则推出递归式
T(P) = T(P-1) + O(1) P>2
O(1) P=2
忽略边界条件,可得递归式T(P) = T(P-1) + c
由递归树方法可得 T(P) = O(P)
c). 算法分析:
由于Young氏矩阵未满,则A[m, n] = ∞。然后将A[m, n]更新为插入值后,可能违反了Young氏矩阵的性质。所以需中采用了类似INSERT-SORT的插入循环方式,从插入节点[m, n]往矩阵的左上方移动,寻找合适的位置,保持Young氏矩阵的性质。在移动的过程中此元素不断与左侧(或上方)矩阵元素比较,如果此元素关键字小于左侧(或上方)元素,则交换它们的关键字,继续向左移动(或向上移动)。反复与左侧和上方元素比较,直至该元素均大于左侧和上方元素,程序终止。
YOUNG-INSERT(A, key)
A[row[A], col[A]] ← key
i ← row[A]
j ← col[A]
while i ≥ 1 and j ≥ 1
do if i > 1 and A[i - 1, j] > A[i, j]
then exchange(A[i -1, j], A[i, j])
i ← i - 1
else if j > 1 and A[i, j - 1] > A[i, j]
then exchange(A[i, j -1], A[i, j])
j ← j - 1
else return;
复杂度分析类似于b),T(P) = O(P)=O(m+n)
d). 算法分析,首先构造一个n*n矩阵A,元素均赋值为∞,满足Young氏性质,将n*n个元素逐个调用 YOUNG-INSERT,插入矩阵A中。然后,调用YOU-G-EXTRACT-MIN(A, i, j) n*n次,并将返回值逐个插入数组中。
YOUNG-SORT(C)
create matrix A[1...n, 1...n]for i ← 1 to n
do for j ← 1 to n
do A[i, j] ← ∞
for i ← 1 to n*n
do YOUNG-INSERT(A, C[i])
for i ← 1 ton*n
do C[i] = YOUNG-EXTRACT-MIN(A, 1, 1)
复杂度分析:YOUNG-SORT过程时间代价为O(n3),其中每次调用YOUNG-INSERT与YOUNG-EXTRACT-MIN复杂度为O(n),共调用了n2次。
e).
总是于最右上角的元素X比较;
1)如果==X,结束;2)如果比X小,那么元素只可能在前N-1列中;
3)如果比X大,那么元素只可能在后M-1行中;
Young 氏矩阵去掉一行或一列还是 Young 氏矩阵;
所以每次比较最少去掉一行或一列,这样复杂度就是 O(m+n);
SEARCH(A, key)
m ← row[A]n ← col[A]
i ← 0
j ← n
while i ≤ n and j ≥ 1
if A[i ,j] > key
then j ← j - 1
else if A[i ,j] < key
then i ← i - 1
else return (i, j)
return "Not Found"