給定結點權值,求哈夫曼樹的帶權路徑長度和
阿新 • • 發佈:2019-01-24
1.哈夫曼樹概念
一棵樹中,從任意一個結點到達另一個結點的通路叫做路徑,該路徑包含的邊的個數稱為路徑長度,每個結點帶有的表示某種意義的值成為權值。從根結點到葉子結點的路徑長度乘以葉子節點權值,得到的值為該節點的帶權路徑長度,樹中所有葉子節點的帶權路徑長度之和稱為該樹的帶權路徑長度和。給定N個結點和它們的權值,以這N個結點為葉子節點構造的帶權路徑長度和最小的二叉樹,就是哈夫曼樹。
2.C語言實現給定結點,求哈夫曼樹的帶權路徑長度和
哈夫曼樹帶權路徑長度和求解演算法:
(1)所有結點權值放入集合K,並始終保持K中元素按從小到大排序(使用優先佇列priority_queue)。
(2)if K中結點數目不小於1,取前兩個元素a,b相加,並彈出前兩個元素a,b,將所得的和插入集合K(插入後K中元素順序依然保持從小到大);if K中結點數目只有1,這個就是根節點的權值。
(3)所有中間結點權值相加(即把所有a+b求和),即為所求哈夫曼樹帶權路徑長度和(根據(路徑長度*權值)求和的公式很容易推出來)
注意:使用優先佇列,即堆資料結構,使得我們可以以O(logn)的時間複雜度就取出集合中最小的前兩個元素a,b,具體原理,可以參考堆結構的相關知識。
#include<queue> #include<functional> priority_queue<int, vector<int>, greater<int>> Q; int main() { int n; while (scanf_s("%d", &n) != EOF) { while (!Q.empty()) Q.pop(); for (int i = 0; i < n; i++) { int tmp; scanf_s("%d", &tmp); Q.push(tmp); } int ans = 0; while(Q.size()>1){ int a, b; a = Q.top(); Q.pop(); b = Q.top(); Q.pop(); ans += (a + b); Q.push(a + b); } printf("%d", ans); } return 0; }