1. 程式人生 > >POJ 1521 哈夫曼編碼 貪心法

POJ 1521 哈夫曼編碼 貪心法

題意:給定字串,求哈夫曼編碼長和它與等長編碼的比值,比較基礎

思路:這題考查哈弗曼編碼,但其實沒必要建樹得出編碼,只需要統計哈弗曼編碼後的總碼長即可

參考了網友的題解,用到了優先權佇列維持一個從小到大的序列

第38行其實就是把越小的頻數反覆多加幾次,越大的頻率少加幾次,體現了字首碼的設計思想

Source Code

Memory: 232K Time: 0MS
Language: C++ Result: Accepted
//這題考查哈弗曼編碼,但其實沒必要建樹得出編碼,只需要統計哈弗曼編碼後的總碼長即可
#include <iostream>
#include <queue>
using namespace std;

class mycomparison
{
public:
  bool operator() (const int& lhs, const int&rhs) const
  {
    return (lhs > rhs);//使得從小到大排序,佇列頭為最小元素,優選權佇列預設佇列頭最大
  }
};

int main(){
	char s[500];
	int count[200] = {0};//count[i]記錄ASCII碼為i的字元的個數
	int i, sum, len;
	priority_queue<int, vector<int>, mycomparison> pq;
	while(cin>>s){
		if(!strcmp(s,"END")){
			break;
		}
		len = strlen(s);
		for(i = 0; i < len; i++){
			count[s[i]]++;
		} 
		sum = 0;
		for(i = 0;i < 200; i++){
			if(count[i]){
				pq.push(count[i]);
				count[i] = 0;
			}
		}
		while(pq.size() > 1){
			int a = pq.top(); pq.pop();
			int b = pq.top(); pq.pop();
			sum += a + b;//其實就是把越小的頻率反覆多加幾次,越大的頻率少加幾次
			pq.push(a + b);
		}
		if(!sum){
			sum = len;//此時pq中只有一個元素
		}
		while(!pq.empty()){
			pq.pop();
		}
		printf("%d %d %.1f\n",8*len,sum,double(double(8*len)/sum));//注意精度設定
	}
	return 0;
}