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