九度题目1172:哈夫曼树

原题链接: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

(图片来源:http://www.cnblogs.com/mcgrady/p/3329825.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;
}



如果文章有什么错误或者有什么建议,欢迎提出,大家共同交流,一起进步

文章转载请注明出处,请尊重知识产权

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值