第十六章 貪心演算法
總結:這一章通過作用選取範圍問題引出貪心演算法,講了貪心策略的基本思想,並介紹了用了貪心策略的赫夫曼編碼。
1. 貪心策略的基本思想
對有些最佳化問題可以使用貪心演算法來解決,貪心演算法期望通過所做的局部最優選擇來產生出一個全域最優解。但並不是所有最佳化問題都可通過貪心演算法來解決的。
貪心演算法的步驟:
1) 將最佳化問題轉化成這樣的一個問題,即先做出選擇,再解決剩下的一個子問題。
2) 證明原問題總是有有一個最優解是做貪心選擇得到的,從而說明貪心選擇的安全。
3) 說明在做出貪心選擇後,剩餘的子問題具有這樣的一個性質。即如果將子問題的最優解和我們所做的貪心選擇聯合起來,可以得出原問題的一個最優解。
貪心選擇性質:一個全域最優解可以通過局部最優(貪心)選擇來達到。即當考慮做何選擇時,我們只考慮對當前問題最佳的選擇而不考慮子問題的結果。
使用貪心演算法,必須做兩個證明:
1) 證明每一步所做的貪心選擇最終能產生一個全域最優解。在證明中先考察一個全域最優解,然後證明對該解加以修改,使其採用貪心選擇,這個選擇將原問題變為一個相似的、但更小的問題。
2) 假設原問題中做了一個貪心選擇而得到了一個子問題。證明將此子問題的最優解與所做的貪心選擇合并後,的確可以得到原問題的一個最優解。
貪心演算法與動態規劃:
在動態規劃中,每一步都要做出選擇,但是這些選擇依賴於子問題的解。因此,動態規劃一般是自底向上,從小子問題處理至大子問題。
在貪心演算法中,我們所做的總是當前看似最佳的選擇,然後再解決選擇之後出現的子問題。貪心策略是自頂向下的,不斷地將給定的問題執行個體規約為更小的問題。
2. 赫夫曼編碼
首碼編碼:沒有一個編碼是另一個編碼的首碼。
HUFFMAN編碼是最優首碼碼的貪心演算法,在每一步所有可能的合并中,選擇一個代價最小的合并。
設C是一個包含n個字元的集合,對C中的每個字元c,f[c]代表c出現的頻度。顯然,對出現頻度大的字元,對它的編碼的長度應該儘可能小。
虛擬碼
HUFFMAN(C)
n <- |C|
Q <- C
for i <- 1 to n
do allocate a new code z
left[z] <- x <- EXTRACT-MIN(Q)
right[z] <- y <- EXTRACT-MIN(Q)
f[z] <- f[x]+f[y]
INSERT(Q,z)
return EXTRACT-MIN(Q)
其中,Q是一個以f為關鍵字的最小優先順序隊列,可以用最小二元堆積實現。
複雜度分析:O(nlgn)