《算法導論》第六章 練習題 Exercise
6.1-1
在高度為 h 的堆中,元素最多有 2h+1 - 1 個,最少有 2h 個。註意算法導論裏的高度是指深度,從 0 開始而不是從 1 開始。
6.1-2
這很好想,但是不好證明。
由已知高度為 h 的堆,它的元素個數滿足 2h <= n <= 2h+1 - 1 ,解出 lg(n+1) - 1 <= h <= lgn ,但是它不夠“合理”,因為當 n = 2h+1-1 時,n 等於 2的冪 - 1,此時 lg(n+1) -1 = ?lgn? ,所以 ?lgn? <= h <= lgn 。而我們默認高度 h 是一個自然數,所以左右界一致,得出 h = ?lgn? 。
6.1-3
最大堆的屬性告訴我們除了根結點以外的所有結點都要滿足 A[PARENT(I)] >= A[I] ,一棵樹是遞歸定義的,所以子樹的最大結點肯定是其根結點。
6.1-4
它一定是葉子結點,位於 ?lgn? 或 ?lgn? - 1 層
6.1-5
按遞增排序的話,是的
6.1-6
不是,"PARENT" 6 < "CHILD" 7
6.1-7
通過反證法比較好證明。
假設 i ∈ { ?n/2?+1, ?n/2?+2, ... , n } ,那麽它的孩子的序號至少是 2·(?n/2?+1), 2·(?n/2?+2) ,顯然不在數組內。
所以可以得到結論:堆中葉子結點數 = ?n+1?
6.2-1
3 先與左右兒子比較,找到其中最大的關鍵字並記錄它的索引,讓它與 3 交換,遞歸調用實現 3 的子樹堆化。
6.2-2
維護最小堆的算法如下:
#define LEFT(i) (2*i + 1) #define RIGHT(i) (2*i + 2) MIN-HEAPIFY (A, i) left = LEFT (i) right = RIGHT (i) if left <= A.HEAPSIZE && A[left] < A[i] min_index= left else min_index = i if right <= A.HEAPSIZE && A[right] < A[min_index] min_index = right if min_index != i exchange A[i] and A[min_index] MIN-HEAPIFY(A, min_index)
時間一樣,都是 Θ(lgn)
6.2-3
不會進行遞歸堆化。
6.2-4
其子結點的序號超出了堆的大小,程序將視為其子結點不存在,所以不會進行堆化操作。
6.2-5
尾遞歸改循環控制結構如下:
#define LEFT(i) (2*i + 1) #define RIGHT(i) (2*i + 2) MAX-HEAPIFY (A, i) while i < A.HEAPSIZE left = LEFT(i) right = RIGHT(i) if left < A.HEAPSIZE && A[left] > A[i] max_index = left else max_index = i if right < A.HEAPSIZE && A[right] > A[max_index] max_index = right if max_index != i exchange A[max_index] and A[i] else return;
6.2-6
...
6.3-1
從 ?A.length/2? 開始,即第一個非葉子結點 10 開始(最大)堆化,然後是 3、2、1 。過程很簡單,直接寫結果了,得到的數組是 {84, 22, 19, 10, 3, 17, 6, 5, 9}
6.3-2
我們從 ?n/2? 開始的目的是要讓每次叠代前後 i 都是最大堆的根。如果從 1 開始,那麽將無法保持最大堆的特性(無法保證循環不變式)。
6.3-3
這裏將利用到 6.1-7 的結論:堆中葉子結點數 = ?n/2?
首先,當 h = 0 時(算法導論中高度深度都是從 0 開始),高度為零的堆就是葉子結點組成的堆,有 ?n/2? 個這樣的堆,結點數是 ?n/2?
假設當 h = h-1 時,結論成立。
有一顆高度為 h 的堆,如果把它的葉子結點都剪去後它將變成高度為 h - 1 、結點數為 n - ?n/2? = ?n/2? 的堆,代入 h = h-1 時的結論,有如下推導:
同理,我們可以用高度為 h+1 的堆剪去葉子結點得到高度為 h 的堆,其高度與最大結點數的關系還是上式。
《算法導論》第六章 練習題 Exercise