您的位置:首页 > 其它

九度题目1172:哈夫曼树

2014-04-15 17:02 369 查看
原题链接:http://ac.jobdu.com/problem.php?pid=1172

题目描述:

哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。

输入:

输入有多组数据。

每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。

输出:

输出权值。

样例输入:
5
1 2 2 5 9


样例输出:
37


本题用到了优先队列这种数据结构,说实话,原来也没有用过,在优先队列中,元素被赋予优先级。当访问元素时,

具有最高优先级的元素最先删除,我感觉我们只需要知道

priority_queue<int> q;
priority_queue< int,vector<int>,greater<int> > q2;

void f(){
int i;
for(i=0;i<5;i++){
q.push(i);
}
for(i=0;i<5;i++){
cout<<q.top()<<" ";
q.pop();
}
cout<<endl;
}

void g(){
int i;
for(i=0;i<5;i++){
q2.push(i);
}
for(i=0;i<5;i++){
cout<<q2.top()<<" ";
q2.pop();
}
cout<<endl;
}
的结果分别是

4 3 2 1 0

0 1 2 3 4

默认的出对顺序是权值较大的,添加了greater<int>之后,就正好相反了

当然调用priority_queue< int,vector<int>,greater<int> >这个数据结构的时候,需要引用

#include  <queue>
#include <functional>


有了这些预备知识,数据结构的问题就不用担心了,我们就能每次都取出最小的两个数
哈夫曼树的创建的过程就是每次取出当前最小的两个数,然后相加合并,树增高一层,最后权值就是树高*叶子节点的权值,如本题的1 2 2 5 9,37=(1+2)*4+2*3+5*2+9


(图片来源:/article/4853662.html)

我意外的的发现,例如上图求权值,求2 5 7 13的最小带权路径就是(2+5)*3+7*2+13=48

其实也可以这样算,就是所有的非叶子节点之和,即27+14+7=48,测试用例中的37也可以这么算37=19+10+5+3

我的程序就是这么写的,想想也对,非叶子节点不就是所有的叶子节点加起来的吗?理论的证明这个还需要参考

代码如下:

#include <iostream>
#include <functional>
#include <queue>
using namespace std;

int main(int argc, char** argv) {
int n,i;
priority_queue< int,vector<int>,greater<int> >q;
while(cin>>n){
int tmp;
for(i=0;i<n;i++){
cin>>tmp;
q.push(tmp);
}
int ans=0;
while(q.size()!=1){
int num1=q.top();
q.pop();
int num2=q.top();
q.pop();
int result=num1+num2;
ans+=result;
q.push(result);
}
q.pop();
cout<<ans<<endl;
}
return 0;
}


如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步
文章转载请注明出处,请尊重知识产权
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: