在一棵樹中,從任意乙個結點到達另乙個結點的通路被稱為路徑,該路徑上所需要經過的邊的個數被稱為該路徑的長度。從根節點到達該結點的路徑長度再乘以該結點權值被稱為該結點的帶權路徑長度。樹中所有葉子節點的帶權路徑長度之和為該樹的帶權路徑長度和。給定n個結點和它們的權值,以它們為葉子結點構造一棵帶權路徑長度和最小的二叉樹,該二叉樹即為哈夫曼樹,同時也被稱為最優樹。題目描述 給定結點的哈弗曼樹可能不唯一,所以關於哈弗曼樹的機試題往往需要求解的是其最小帶權路徑長度和。回顧一下我們所熟知的哈弗曼樹求法。
(1) 將所有結點放入集合k。
(2) 若集合k中剩餘結點大於2個,則取出其中權值最小的兩個結點,構造它們同時為某個新結點的左右子結點,該新結點是他們共同的雙親結點,設定它的權值為其兩個孩子結點的權值和。並將該父親結點放入集合k。重複步驟(2)或(3)。
(3) 若集合k中僅剩乙個結點,該結點即為構造出的哈弗曼樹的根結點,所有構造得到的中間結點(即哈弗曼樹上非葉子節點)的權值和即為該哈弗曼樹的帶權路徑和。
為了方便快捷高效率的求得集合k中權值最小的兩個元素,我們需要使用堆資料結構。它可以以o(logn)的複雜度取得n個元素中的最小元素。為了繞過對堆的實現,我們使用標準模板庫中的相應的標準模板-優先佇列。
利用語句
priority_queueq;
建立乙個儲存元素為
int
的堆q,但是請特別注意這樣建立的堆其預設為大頂堆,即我們從堆頂取的的元素為整個堆中最大的元素。而在求哈弗曼樹中,我們恰恰需要取得堆中最小的元素,於是我們使用如下語句定義乙個小頂堆:關於堆的有關操作如下:priority_queue<
int,vector<
int>>
,greater<
int>> q;
將元素x放入堆q中q.
push
(x);
取出堆頂元素,即最小的元素儲存在a中。int a = q.
top(
);
彈出堆頂元素,取出後堆會自動調整為乙個新的小頂堆。q.
pop(
);
哈弗曼樹,第一行輸入乙個數n,表示葉結點的個數。需要用這些葉結點生成哈弗曼樹,根據哈弗曼樹的概念,這些結點有權值,即weight
,題目需要輸出所有結點的值與權值的乘積之和。
輸入: 輸入有多組資料。每組第一行輸入乙個數n
,接著輸入n
個葉結點(葉結點權值不超過100,2<=n<=1000)。
輸出: 輸出權值
樣例輸入:
512259
樣例輸出:37
#include
#include
#include
using namespace std;
priority_queue<
int,vector<
int>
,greater<
int>
> q;
// 建立乙個小頂堆
intmain
(void
)int ans =0;
// 儲存答案
while
(q.size()
>1)
printf
("%d\n"
,ans);}
return0;
}
執行結果: 資料結構 哈夫曼樹與哈夫曼編碼
1 路徑 由乙個結點到另乙個結點之間的所有分支共同構成。2 路徑長度 結點之間的分支數目。3 樹的路徑長度 從樹的根結點到其他所有結點的路徑長度之和。4 權 賦予某一實體的值。在資料結構中,實體包括結點和邊,所以對應有結點權和邊權。5 結點的帶權路徑長度 結點與樹的根結點之間的路徑長度與結點權的乘積...
資料結構 哈夫曼樹與哈夫曼編碼
include pch.h include 哈夫曼樹類huffmantree的定義 huffman樹結點類treenode宣告 template class t class huffmannode 建構函式 huffmannode getleft void const void setleft hu...
資料結構哈夫曼樹演算法
include using namespace std if defined huffmantree h define huffmantree h 哈夫曼樹結構 lass huffmantree typedef char huffmancode 從結點集合中選出權值最小的兩個結點 將值分別賦給s1和...