【九度OJ-1172】 哈夫曼数

九度oj地址:http://ac.jobdu.com/problem.php?pid=1172


时间限制:1 秒

内存限制:32 兆

特殊判题:

提交:8168

解决:3641

题目描述:

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

输入:

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

输出:

输出权值。

样例输入:
5  
1 2 2 5 9
样例输出:
37
来源:
2010年北京邮电大学计算机研究生机试真题

第一种方法:不建树,这种方法要简单一点

[cpp]  view plain  copy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <algorithm>  
  4. #include<iostream>  
  5. #include<stack>  
  6. using namespace std;  
  7. int result[1001];  
  8. //哈夫曼树的权值就是除了所有叶子  
  9. //的节点的权值的和  
  10. int main(){  
  11.     int n,i,sum,num;  
  12.     while(scanf("%d",&n)!=EOF){  
  13.         memset(result,0,n);  
  14.         for(i=0;i<n;i++)  
  15.             scanf("%d",&result[i]);  
  16.         //进行排序,从小到大  
  17.         sort(result,result+n);  
  18.         i=1;  
  19.         sum=0;  
  20.         while(i<n){  
  21.             //每次都要进行重新排序,因为生成了新的节点  
  22.            sort(result+i-1,result+n);  
  23.            //计算父亲  
  24.            num = result[i-1]+result[i];  
  25.            sum+=num;  
  26.            //将新的节点赋值  
  27.            result[i]=num;  
  28.            i++;  
  29.         }  
  30.         printf("%d\n",sum);  
  31.     }  
  32.     return 0;  
  33. }  


第二种方法:建树

[cpp]  view plain  copy
  1.   
[cpp]  view plain  copy
  1. <pre name="code" class="cpp">#include <stdio.h>  
  2. #include <string.h>  
  3. #include <algorithm>  
  4. #include<iostream>  
  5. #include<stack>  
  6. #define maxvalue 0x7fffffff//这个是int的最大值  
  7. using namespace std;  
  8. //创建节点的结构体  
  9. struct huffman{  
  10.     int weight;  
  11.     int parent,lchild,rchild;  
  12. }list[5000];  
  13. int main()  
  14. {  
  15.     int n,m;  
  16.     int i,j;  
  17.     int ans;  
  18.     int x1,x2;//用来存放树生成过程中的最小和次小的角标  
  19.     int m1,m2;//用来存放树生成过程中的最小和次小的值  
  20.     while(scanf("%d",&n)!=EOF)  
  21.     {  
  22.         m=2*n-1;  
  23.         for(i=0;i<m;i++)  
  24.         list[i].parent=list[i].lchild=list[i].rchild=-1;  
  25.         for(i=0;i<n;i++)  
  26.         scanf("%d",&list[i].weight);  
  27.         ans=0;  
  28.         for(i=0;i<n-1;i++){  
  29.             x1=x2=0;  
  30.             m1=m2=maxvalue;  
  31.             for(j=0;j<n+i;j++){  
  32.                 //用来判断新的节点是否小于最小且没有双亲  
  33.                 //如果小于最小的话就把当前的数和角标给x1和m1  
  34.                 //并且在x1和m1中存入当前最小的角标和值  
  35.                 if(list[j].weight<m1&&list[j].parent==-1){  
  36.                     x2=x1;  
  37.                     m2=m1;  
  38.                     x1=j;  
  39.                     m1=list[j].weight;  
  40.                 }  
  41.                //用来判断是不是小于次小,如果小于的话就替换次小  
  42.                 else if(list[j].weight<m2&&list[j].parent==-1){  
  43.                     x2=j;  
  44.                     m2=list[j].weight;  
  45.                 }  
  46.             }  
  47.             list[x1].parent=n+i;  
  48.             list[x2].parent=n+i;  
  49.             list[n+i].lchild=x1;  
  50.             list[n+i].rchild=x2;  
  51.             list[n+i].weight=list[x1].weight+list[x2].weight;  
  52.             ans+=list[n+i].weight;  
  53.         }  
  54.         printf("%d\n",ans);  
  55.     }  
  56.     return 0;  
  57. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值