3.哈夫曼树,第一行输入一个数n,表示叶节点的个数。需要用这些叶节点生成哈夫曼树。这些节点
有权值,即weight,题目需要输出所有节点的值与权值的乘积之和。输出权值
5
1 2 2 5 9
有权值,即weight,题目需要输出所有节点的值与权值的乘积之和。输出权值
5
1 2 2 5 9
37
思路:将所有节点放入集合K,若K中剩余节点大于2,则取出最小的两个节点,构造他们同时为某个节点的左右子节点,则该新节点的权值为左右儿子节点权值之和,并将该节点放入集合K。若集合K只余一个节点,则该节点为哈夫曼树的根节点。所有构造得到的中间节点的权值和即为哈夫曼树的带权路径和。在此使用小顶堆来取集合K中最小的两个值。堆结构用标准模板库中的优先队列实现。
#include<queue> #include<stdio.h> using namespace std; priority_queue<int, vector<int>,greater<int> > Q; //建立一个小顶堆 int main() { int n; while(scanf("%d",&n)!=EOF) { while(Q.empty()==false) Q.pop();//清空堆中元素 for(int i=1;i<=n;i++)//输入n个叶子节点权值 { int x; scanf("%d",&x); Q.push(x); } int ans=0;//保存答案 while(Q.size()>1) {//取出堆中两个最小元素,他们为同一个节点的左右儿子,且该双亲节点的权值为他们的和 int a=Q.top(); Q.pop(); int b=Q.top(); Q.pop(); ans+=(a+b);//该父亲节点必为非叶子节点,故累加其权值 Q.push(a+b);//将双亲节点的权值放入堆中 } printf("%d\n",ans); } return 0; }哈夫曼树所求为最小权值路径之和:所有节点权值与节点路径长度乘积之和。即使权值最小的节点路径较长,权值大的,路径较短。所以即为所有构造节点权值之和。因为构造节点为原节点累加而来,之后树高每增加一次,构造节点累加,相当于底层节点按路径长度累加,相当于权值乘以路径长度。