hdu 1053 哈夫曼树 优先队列

原创 2015年11月17日 16:26:27
此题关于哈夫曼编码。
哈夫曼树(霍夫曼树)又称为最优树.
基本术语:
1、路径和路径长度
在一棵树中,从一个结点往下可以达到的孩子或孙子结点之间的通路,称为路径。通路中分支的数目称为路径长度。若规定根结点的层数为1,则从根结点到第L层结点的路径长度为L-1。
2、结点的权及带权路径长度
若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。
3、树的带权路径长度
树的带权路径长度规定为所有叶子结点的带权路径长度之和,记为WPL。
构造:
假设有n个权值,则构造出的哈夫曼树有n个叶子结点。 n个权值分别设为 w1、w2、…、wn,则哈夫曼树的构造规则为:
(1) 将w1、w2、…,wn看成是有n 棵树的森林(每棵树仅有一个结点);
(2) 在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左、右子树,且新树的根结点权值为其左、右子树根结点权值之和;
(3)从森林中删除选取的两棵树,并将新树加入森林;
(4)重复(2)、(3)步,直到森林中只剩一棵树为止,该树即为所求得的哈夫曼树。
哈夫曼编码
在数据通信中,需要将传送的文字转换成二进制的字符串,用0,1码的不同排列来表示字符。例如,需传送的报文为“AFTER DATA EAR ARE ART AREA”,这里用到的字符集为“A,E,R,T,F,D”,各字母出现的次数为{8,4,5,3,1,1}。现要求为这些字母设计编码。要区别6个字母,最简单的二进制编码方式是等长编码,固定采用3位二进制,可分别用000、001、010、011、100、101对“A,E,R,T,F,D”进行编码发送,当对方接收报文时再按照三位一分进行译码。显然编码的长度取决报文中不同字符的个数。若报文中可能出现26个不同字符,则固定编码长度为5。然而,传送报文时总是希望总长度尽可能短。在实际应用中,各个字符的出现频度或使用次数是不相同的,如A、B、C的使用频率远远高于X、Y、Z,自然会想到设计编码时,让使用频率高的用短码,使用频率低的用长码,以优化整个报文编码。
为使不等长编码为前缀编码(即要求一个字符的编码不能是另一个字符编码的前缀),可用字符集中的每个字符作为叶子结点生成一棵编码二叉树,为了获得传送报文的最短长度,可将每个字符的出现频率作为字符结点的权值赋予该结点上,显然字使用频率越小权值越小,权值越小叶子就越靠下,于是频率小编码长,频率高编码短,这样就保证了此树的最小带权路径长度效果上就是传送报文的最短长度。因此,求传送报文的最短长度问题转化为求由字符集中的所有字符作为叶子结点,由字符出现频率作为其权值所产生的哈夫曼树的问题。利用哈夫曼树来设计二进制的前缀编码,既满足前缀编码的条件,又保证报文编码总长最短。

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
struct node
{
	int x;
	friend bool operator <(node a,node b)
	{
		return a.x > b.x;
	}
};
char s[500];
int num[27];
int main()
{
//	freopen("t.txt","r",stdin);
	priority_queue<node>q;
	node temp1,temp2;
	int i,j,l,ans;
	while(gets(s))
	{
		ans = 0;
		while(!q.empty())q.pop();
		memset(num,0,sizeof(num));
		if(!strcmp(s,"END")) break;
		l = strlen(s);
		for(i = 0; i < l; i++)
		{
			if(s[i] == '_') num[0]++;
			else num[s[i] + 1 - 'A']++;
		}
		for(i = 0; i <= 26; i++)
		{
			if(num[i] == 0) continue;
			temp1.x = num[i];
			q.push(temp1);	
		}
		if(q.size() == 1) 
		{
			printf("%d %d %.1lf\n",8*l,temp1.x,(8*l*1.0/temp1.x));
			continue;
		}
		while(q.size() > 1)
		{
			temp1 = q.top(); q.pop();
			temp2 = q.top(); q.pop();
			ans += temp1.x + temp2.x;
			temp1.x = temp1.x + temp2.x;
			q.push(temp1);
		}
		printf("%d %d %.1lf\n",8*l,ans,(8*l*1.0/ans));
		
	}
}



版权声明:转载注明出处。有任何疑问可留言。

相关文章推荐

c++使用优先队列来构建huffman树[哈夫曼树]

#include #include #include #include #include using namespace std; char Table[26]; struct Node...
  • realxie
  • realxie
  • 2011年12月18日 17:28
  • 2295

哈夫曼编码问题再续(下篇)——优先队列求解

上篇描述了哈夫曼编码问题的基本描述以及建造一个哈夫曼树的过程分析,那么当算法已经描述清楚之后,我们要怎么样来实现 代码呢?或者说,给你一些带有权值的叶子节点,要怎么样利用程序快速算出所对应的哈夫曼树...

利用优先队列编写哈夫曼树和编码

利用“有序链表”来实现优先队列,链表元素按优先级递减。元素出列即出首元素,元素入列即将元素插入有序链表使其依然有序。本程序中,字符频率小则优先级高。 typedef int PQElemType...

优先级队列(哈夫曼树)poj3253

题目链接:http://poj.org/problem?id=3253 题目解析:根据Hint提示我们可知,就是求锯木段的最小费用;而每次锯木段的费用就是锯下的木段的长度,那么自然就是短的先搞定。 ...

HDU1053Entropy哈夫曼求总值+优先队列

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1053   题目解释: 输入一个字符串(只包含26个大写字母和‘_'),每个字母8位,这个字符...

优先队列C++实现哈夫曼树

  • 2012年02月13日 10:23
  • 2KB
  • 下载

poj 3253 Fence Repair【哈夫曼树、优先队列】

点击打开题目 Fence Repair Time Limit: 2000MS   Memory Limit: 65536K Total Submissions...

poj-3253-sdutoj-2127-哈夫曼树-优先队列

Description Farmer John wants to repair a small length of the fence around the pasture. He measures...

POJ 3253 Fence Repair(优先队列构造哈夫曼树)

割木板,割木板的长度就是花的钱。比如你要8 8 5 的木板,最简单的方式是把21的木板割成13,8,花费21,再把13割成5,8,花费13,共计34,当然也可以先割成16,5的木板,花费21,再把16...

哈夫曼树 --- 优先队列(C++STL)

数据结构实验之二叉树六:哈夫曼编码 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description字符...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:hdu 1053 哈夫曼树 优先队列
举报原因:
原因补充:

(最多只允许输入30个字)