優先佇列與赫夫曼樹

2022-06-23 14:09:12 字數 2048 閱讀 9469

1.赫夫曼樹

帶權路徑最短的二叉樹,亦稱為最優二叉樹。在壓縮編碼方面,求解最小帶權和方面有著重要應用。往往機試題即是求最小的帶權長度和,如典型的合併石子問題。在解決這類問題時,一般可分為以下幾個方面:

首先將所有節點放入集合k,同時初始化全域性變數ans=0;

然後從集合k中選出最小權值的兩個節點,將他們的和sum放入k,更新ans為ans+sum,同時從k中刪除這兩個節點;

若集合k中只剩乙個節點時,即為根節點,輸出的ans即為帶權路徑的總長度。

2.優先佇列

基於赫夫曼樹在求解最小帶權路徑和方面時,每次都是從集合k

kk中選取出最小的兩個值,我們可以利用優先佇列的特徵,維持乙個小頂堆,每次取出小頂堆堆頂的兩個值,同時將他們的和放入堆中,利用ans

ansan

s統計每次的和,然後彈出這兩個值。當堆裡只有乙個元素時,輸出的ans

ansan

s即為帶權的路徑和。在取出最小的兩個值時,時間複雜度可將為o(l

ogn)

o(logn)

o(logn

)

#include

using

namespace std;

priority_queue<

int> q;

//預設為大頂堆

priority_queue<

int,vector<

int>

,greater<

int>

> q2;

//小頂堆,注意末尾兩個》有間隔,否則可能報錯

3. 舉個栗子

題目:搬水果

題目描述

在乙個果園裡,小明已經將所有的水果打了下來,並按水果的不同種類分成了若干堆,小明決定把所有的水果合成一堆。每一次合併,小明可以把兩堆水果合併到一起,消耗的體力等於兩堆水果的重量之和。當然經過 n‐1 次合併之後,就變成一堆了。小明在合併水果時總共消耗的體力等於每次合併所耗體力之和。 假定每個水果重量都為 1,並且已知水果的種類數和每種水果的數目,你的任務是設計出合併的次序方案,使小明耗費的體力最少,並輸出這個最小的體力耗費值。例如有 3 種水果,數目依次為 1,2,9。可以先將 1,2 堆合併,新堆數目為3,耗費體力為 3。然後將新堆與原先的第三堆合併得到新的堆,耗費體力為 12。所以小明總共耗費體力=3+12=15,可以證明 15 為最小的體力耗費值。

輸入描述:

每組資料輸入包括兩行,第一行是乙個整數 n(1<=n<=10000),表示水果的種類數。第二行包含 n 個整數,用空格分隔,第 i 個整數(1<=ai<=1000)是第 i 種水果的數目。

輸出描述:

對於每組輸入,輸出乙個整數並換行,這個值也就是最小的體力耗費值。輸入資料保證這個值小於 2^31。

示例1

輸入

3

9 1 2

輸出

思路:利用優先佇列維持乙個小頂堆,然後用ans

ansan

s統計總的體力值即可。

#include

#include

#include

#include

using

namespace std;

priority_queue<

int,vector<

int>

,greater<

int>

> q;

//公升序優先佇列實現最小堆

intmain()

int ans=0;

while

(q.size()

>1)

printf

("%d\n"

,ans)

;return0;

}

參考資料

《計算機考研機試指南》

哈夫曼樹,赫夫曼樹

參考 赫夫曼樹,別名 哈夫曼樹 最優樹 以及 最優二叉樹 當用 n 個結點 這些結點都作為葉子結點且都有各自的權值 試圖構建一棵樹時,如果構建的這棵樹的帶權路徑長度最小,稱這棵樹為 最優二叉樹 有時也叫 赫夫曼樹 或者 哈夫曼樹 構建哈夫曼樹 在 n 個權值中選出兩個最小的權值,對應的兩個結點組成乙...

赫夫曼樹 樹

在資料膨脹,資訊 的今天,資料壓縮的意義不言而喻。談到資料壓縮,就不能 不提赫夫曼編碼,赫夫曼編碼是首個使用的壓縮編碼方案,即使在今天的知名壓縮演算法裡,依然可以見到赫夫曼編碼的影子。另外,在資料通訊中,用二進位製給每個字元進行編碼時不得不面對乙個問題是如何使電文總長最短且不產生二義性。根據字元出現...

樹 赫夫曼樹

幾個概念 wpl最小的就是赫夫曼樹 赫夫曼樹的建立 將數列 轉成一顆赫夫曼樹的過程 將數列元素從小到大排序 取出最小的兩個元素,生成一棵新的二叉樹,取出的兩個元素作為新二叉樹的子節點 一般權重小的作為子節點 根節點的權重為子節點權重之和 將處理過的兩個元素從列表中刪除,將新的根節點加入列表 重複1 ...