码迷,mamicode.com
首页 > 其他好文 > 详细

【POJ1521】【HDU1053】Entropy 哈夫曼(Huffman)编码

时间:2015-01-22 18:16:34      阅读:175      评论:0      收藏:0      [点我收藏+]

标签:poj1521   hdu1053   entropy   哈夫曼编码   huffman   

#include <stdio.h>
int main()
{
	puts("转载请注明出处谢谢");
	puts("http://blog.csdn.net/vmurder/article/details/43020921");
}


题意:

输出字符串的长度*8、huffman编码长度、两者比值。


题解:

huffman编码:

我们发现对于一个字符串,如果我们把它变成01串,比如ABCDE

那么我们需要

A : 000

B : 001

C : 010

D : 100

E : 101

来表示每一个字符,然后识别的时候就是每三个一识别。

这种编码叫定长编码。


显然对于一个串,它的定长编码长度是串长*定长。

但是其实它可以更短。


如果我们想要识别一个串,就需要所有字符的编码都不为其它编码的前缀,这样才可以成功解码。

而此时我们可以根据出现频率来构造huffman编码,以达到最优解。


构造方法可以见于黑书P245,毕竟它还是很水的,随便看看就能明白。


下面是我要讲的方法:

这种编码最后可以构成一颗二叉树,每个叶子节点都是一种字符,而它的变长编码(Huffman)就是从root到这个节点经过的边的序号序列,而左儿子边序号标0,右儿子边序号标1。


建树方法:先把所有字符按照出现次数作为关键字排序,然后给最小的两个赋一个父亲,然后把这两个叶子节点弹出优先队列,把父亲插入进去,父亲的关键字是儿子的size之和。

最后只剩下一个节点的时候停止。


证明在黑书上有,自己去翻吧,感性的思考一下就是每个点都有深度,然后∑深度*size=ans,

我们需要让size大的深度尽量小。


呃,虽然上面的证明显然是在chedan,但是,,并没有但是。


代码:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1000
using namespace std;
char s[N];
int cnt[N];
priority_queue<int>q;
int ans,len;
int main()
{
	freopen("test.in","r",stdin);
	int i,j,k;
	while(scanf("%s",s)!=EOF)
	{
		while(!q.empty())q.pop();
		len=strlen(s),ans=0;
		if(len==3&&s[0]=='E'&&s[1]=='N'&&s[2]=='D')return 0;
		memset(cnt,0,sizeof cnt);
		for(i=0;s[i];i++)cnt[s[i]]++;
		for(i=0;i<N;i++)if(cnt[i])q.push(-cnt[i]);
		for(;;)
		{
			i=q.top(),q.pop();
			if(q.empty())break;
			j=q.top(),q.pop();
			ans-=(i+j);
			q.push(i+j);
		}
		if(!ans)ans=len;
		printf("%d %d %.1lf\n",len*8,ans,(double)len*8/(double)ans);
	}
	return 0;
}


【POJ1521】【HDU1053】Entropy 哈夫曼(Huffman)编码

标签:poj1521   hdu1053   entropy   哈夫曼编码   huffman   

原文地址:http://blog.csdn.net/vmurder/article/details/43020921

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!