1. 程式人生 > >給定結點權值,求哈夫曼樹的帶權路徑長度和

給定結點權值,求哈夫曼樹的帶權路徑長度和

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;
}