给定结点权值,求哈夫曼树的带权路径长度和

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

点赞