算法導論讀書筆記(16)貪心算法

第四部分 高級設計和分析技術

第16章 貪心算法

貪心算法在每一步都做出當時看起來最佳的選擇,它總是做出局部最優的選擇,寄希望這樣的選擇能導致全局最優解。

1. 活動選擇問題

有一個需要使用每個資源的n個活動組成的集合S= {a1,a2,···,an },資源每次只能由一個活動使用。每個活動ai都有一個開始時間si和結束時間fi,且 0≤ si < fi <∞ 。一旦被選擇後,活動ai就佔據半開時間區間[si,fi)。如果[si,fi]和[sj,fj]互不重疊,則稱ai和aj兩個活動是兼容的。該問題就是要找出一個由互相兼容的活動組成的最大子集。例如下圖所示的活動集合S,其中各項活動按照結束時間單調遞增排序。
這裏寫圖片描述
從圖中可以看出S中共有11個活動,最大的相互兼容的活動子集爲:{a1,a4,a8,a11,}和{a2,a4,a9,a11}。

遞歸貪心算法

貪心算法通常採用自頂向下的設計,因爲不需要做出過多的選擇而求解所有的子問題。
Recursive-Activity-Selector(s, f, k, n)
m = k + 1

// find the first activity in Sk to finish
while m <= n and s[m] < f[k]
    m = m + 1

if m <= n
    return {am} U Recursive-Activity-Selector(s, f, m, n)
else
    return Ø
### 迭代貪心算法
Greedy-Activity-Selector(s, f)
    n = s.length
    A = {a1}
    k = 1
    for m = 2 to n
        if s[m] >= f[k]
            A = A U {am}
            k = m
    return A

2. 貪心算法原理

貪心選擇性質

第一個關鍵要素是該性質:我們可以通過做出局部最優(貪心)選擇來構造全局最優解。換句話說,當進行選擇時,我們直接做出在當前問題中看來最優的選擇,而不必考慮子問題的解。
動態規劃方法中,每個步驟都要進行一次選擇,但選擇通過依賴於子問題的解。因此,我們通常以一種自底向上的方式來解動態規劃問題,先求解較小的子問題,然後是較大的子問題
貪心算法中,總是做出當時看來最佳的選擇,然後求解剩下的唯一的子問題。

最優子結構

如果一個問題的最優解包含其子問題的最優解,是稱此問題具有最優子結構性質。當應用於貪心算法時,我們通常使用更爲直接的最優子結構。我們可以假定,通過對原問題應用貪心選擇即可得到子問題。我們真正要做的全部工作就是論證:將子問題的最優解與貪心選擇組合在一起就能生成原問題的最優解。

3. 赫夫曼編碼

討論赫夫曼編碼問題,赫夫曼編碼的思想就是變長編碼變長編碼就是讓字符表中出現概率高的字符的編碼長度儘可能小,而出現概率高的字符的編碼長度相對較長。然後還要遵循前綴碼的要求,就是任意一個編碼都不是其他編碼的前綴碼,這樣方便解碼。

構造赫夫曼編碼

Huffman(C)
    n = |C|
    Q = C
    for i = 1 to n
        allocate a new node z
        z.left = x = Extract-Min(Q)
        z.right = y = Extract-Min(Q)
        z.freq = x.freq + y.freq
        Insert(Q, z)
    return Extract-Min(Q)   // return the root of the tree
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章