POJ 1521 , Entropy , Huffman

http://poj.org/problem?id=1521

Entropy

Time Limit: 1000MS Memory Limit: 10000K

P.S. 原题真长

题目大意:

给定一些只包含 大写字母 和 下划线 的字符串,求利用huffman编码的原理,存储每个字符串需要的最少bit数。

Input

The input file will contain a list of text strings, one per line. The text strings will consist only of uppercase alphanumeric characters and underscores (which are used in place of spaces). The end of the input will be signalled by a line containing only the word “END” as the text string. This line should not be processed.

Output

For each text string in the input, output the length in bits of the 8-bit ASCII encoding, the length in bits of an optimal prefix-free variable-length encoding, and the compression ratio accurate to one decimal point.

Sample Input

AAAAABCD
THE_CAT_IN_THE_HAT
END

Sample Output

64 13 4.9
144 51 2.8
(每个字符8bit需要的空间、按huffman编码需要的空间、二者的比值)


解法:

裸的huffman树。把各个字母出现的次数放入优先队列,每次取出其中两个加起来,形成新的结点,再放入队列即可。
在这里学习了一下如何在优先队列里放指针。

200K 0MS 语言选C++ ,选G++会CE
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
using namespace std;
const int inf=105;

class cmp;//由于cmp和C类互相调用,所以在此提前声明 

class C{public:
	C *ls,*rs;
	int t;
	C(){ls=rs=NULL;t=0;}
	friend cmp;
};

class cmp{public:
	bool operator () (C*a,C*b){return a->t > b->t;}//重载小于号时,参数不能是两个指针 
};

int dfs(C* rt,int dep){
	if (!rt->ls && !rt->rs) return rt->t*dep;
	int tot=0;
	if (rt->ls) tot+=dfs(rt->ls,dep+1);
	if (rt->rs) tot+=dfs(rt->rs,dep+1);
	return tot;
}

int main(){
	string s;
	while(cin>>s){
		if (s=="END") return 0;
		int len=s.length();

		double store=0;
		priority_queue<C*,vector<C*>,cmp> q;
	
		C* c[inf];for (int i=0;i<inf;i++) c[i]=new C;
		for (int i=0;i<len;i++) c[s[i]]->t++;
		int tot=0;
		for (int i=0;i<inf;i++)
			if (c[i]->t) q.push(c[i]),tot++;

		if (tot==1) store=len;	//只有一种字母时,队列中只有一个元素,不能建树 
		else{
			C* root;
			while(1){
				C* ls=q.top();q.pop();
				C* rs=q.top();q.pop();
				C* rt=new C;
				rt->ls=ls,rt->rs=rs;
				rt->t=ls->t+rs->t;
				if (q.empty()) {root=rt;break;}
				q.push(rt);
			}
			store=dfs(root,0);
		}
		printf("%d %.0llf %.1llf\n",len*8,store,len*8/store);
		
		for (int i=0;i<inf;i++) delete c[i];
	}
	return 0;
}






©️2020 CSDN 皮肤主题: 大白 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值