優先佇列解哈夫曼編碼問題之帶權路徑長度

2021-07-10 21:04:43 字數 1540 閱讀 9942

先說個生活中的例子

想想醫院,重症急診患者肯定不能像普通患者那樣依次排隊就診,他們就可以插隊了

他比較遲進佇列,但他優先順序高,所以就相對較早出佇列去就診了

優先佇列一般用堆來實現,堆有兩種(具體看這:

對於大根堆實現的優先佇列,總是優先順序高的元素先被刪除;相對的,對於小根堆實現的優先佇列,總是優先順序低的元素先被刪除。

那麼對於大根堆:你權值高,優先順序也高

但對於小根堆,權值低,優先順序才高,剛好相反

大根堆的實現在這:

下面用小根堆來解決解哈夫曼編碼,其實就改幾個符號(大於改小於號,大家可以對比一下)

比如說aabcdca這個字串,我怎麼編碼呢

先統計個字元的出現次數(下面我把次數說成權值吧

a b 

c d3 1

2 1然後構成一顆哈夫曼樹:就權值最小的兩個加起來,將加起來的權值作為他們兩的父親結點,把那兩個剔除,將父親結點加進來然後再把最小的加起來,作為父親結點,直到最後只剩乙個父親結點(哎這裡不怎麼會說,直接看我製作的圖吧)

那麼4個字母就可以編碼成

a:0b:110

c:10

d:111

這樣就將資料壓縮了,本來我們每個用8個bit的二進位制表示。

不過下面我們解決的是帶權路徑長度,就是取每個結點的權值乘以到根結點的長度(就是到根結點有多少條線),再將每個結點的計算記過加起來

以上面的例子為例:wpl = 1*3 +1 *3 + 2*2 + 3*1 = 13 ,

還有一種計算方法,就是把哈夫曼樹除了根結點以外的索引權值加起來

我們從最低加起

wpl =  1 + 1  + 2 + 2 + 4 + 3 = 13

下面就是用第二中方法,看看程式設計實現,看看結果對不

#includeusing namespace std;

class heap

~heap()

void push(int value)

size++;

}int top()

void update(int pos, int n)

if (rchild < n && data[rchild] < data[min_value])

if (min_value != pos)

}void pop()

int heap_size()

};int main()

//因為我們的帶權路徑長度是不用算根結點的,所以下面的迴圈就是剩最後乙個點時結束

//只有乙個結點就直接它的權值就是帶權路徑長度

if (n == 1)

while (heap.heap_size() > 1)

cout<

可以看到跟我們上面的手算的結果是一樣的

優先佇列實現 哈夫曼編碼

用到了優先佇列的知識點,還有dfs演算法。優先佇列主要是為了查詢最小權重樹的時候方便查詢,不用耗費很多的時間從已經產生的樹種依次查詢,具體實現看 dfs主要是用來遍歷樹從而拿到每個字元的編碼,具體實現看 include include include includeusing namespace s...

優先佇列 哈夫曼樹

哈夫曼樹,第一行輸入乙個數n,表示葉結點的個數。需要用這些葉結點生成哈夫曼樹,根據哈夫曼樹的概念,這些結點有權值,即weight,題目需要輸出所有結點的值與權值的乘積之和的最小值。輸入有多組資料。每組第一行輸入乙個數n,接著輸入n個葉節點 葉節點權值不超過100,2 n 1000 輸出權值。示例1 ...

優先佇列實現哈夫曼編碼(貪心法)

構造哈夫曼樹及輸出哈夫曼編碼,優先佇列構造最小堆實現 windows下輸入結束方法 enter,ctrl z,enter 執行結果如下 遍歷哈夫曼樹,列印哈夫曼編碼 void createhuffcode treenode root 如果是葉子結點,列印 if root lchild root rc...