数据结构作业3-4(周)问题B:哈夫曼树

题目描述

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

输入

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

输出

输出权值。

样例输入

2
2 8 
3
5 11 30 

样例输出

10
62

本题我综合了许多人的讲述和方法,一些相关知识(含链接)也列在了文章里面,也是对自个CPP知识的补充,我就寻思别人学校一学期讲的数据结构怎么到我们这半学期不到20课时就能讲完那500多页的书呢。

首先这里先提及一下什么是哈夫曼树
我们首先引用课本中的解释
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

在这里插入图片描述

但是你们应该都很清楚,要是运用课本中的方案又去创建,又去规定的去写答案基本上就写不出来了。尤其是还剩下14天,而且期末考试在这两周内考的有的是。
所以这道题的思路应该是汲取哈夫曼树的精华不去创建树去写

本文中采用了这位大大的想法:

https://blog.csdn.net/xey_csu/article/details/42389191

代码如下

#include <iostream>
#include <queue>
#include <functional>//这步可以省略但我不建议省略
using namespace std; 
int main()
{ 	int n; 
 	while (cin >> n) 
 	{ 	priority_queue<int,vector<int>,greater<int> > q;  //采用小根堆,greater<int>指堆排序后为递减的,即为小根堆(这句话是原作者的,我没动)  
  		int num;  
  		for (int i = 0; i < n; ++i)  
  		{ 	cin >> num;   
   			q.push(num);  				  //push函数是将元素压入队列中
  		}    
  		int weight = 0;  
  		int a, b;  
  		while (q.size() >= 2)  			          //size函数返回队列内元素个数
  		{ 	a = q.top();   			          //top函数访问队头元素
   			q.pop();   				  //pop函数弹出队头元素
   			b = q.top();   
   			q.pop();    
   			q.push(a + b);   
   			sum += a + b;  
  		}   
  		cout << weight << endl; 
 	} 
 	return 0;
}

这里我需要引用其他的一些你需要了解的内容:
代码中出现了一行priority_queue<int,vector<int>,greater<int> > q;

1.C++中优先队列的使用 https://blog.csdn.net/weixin_36888577/article/details/79937886
2.vector是什么且怎么用 https://blog.csdn.net/weixin_41743247/article/details/90635931

这里定义了一个优先队列,它的名字叫做q,可以帮助我们把该队列中的元素从小到大排列并输出,这就和我们考虑的哈夫曼树就有联系了,哈夫曼树要求最高权值的结点应该在整棵树的根节点旁边。从q队列中最小的两个数开始,找出来赋给a和b,并在队列中删除这两个数,接着再将a+b这个值重新进入队列中,q队列会根据自己的属性重新排列数据从小到大,并不断重复这个过程。注意,对于带权的类型的操作应该是 weight += a+b ,不是weight =a +b (或者可以写成weight = 2*a +b,这样更有助于理解),直到队列中剩下一个值,这个值就是最后的weight。

最后OJ系统运行良好(^U^)ノ~YO 咚哒呦!

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值