1. 程式人生 > >POJ1521---哈夫曼編碼,求最優WPL

POJ1521---哈夫曼編碼,求最優WPL

POJ1521---哈夫曼編碼

題目描述

輸入一個字串,長度不超過100,僅由大寫字母和下劃分組成。求用最好的字元編碼方式,令總長度最小。

輸入

多組資料,每組資料在一行上輸入一個字串,格式如前所述

當遇到END時,表示輸入結束

輸出

對應每個輸入,在一行上輸出3個資訊:首先是每個字母按固定長度8bit編碼,字串的總長度,然後是按最優編碼的總長度,最後是前者對後者的比率,保留1位小數。

樣例輸入

AAAAABCD

THE_CAT_IN_THE_HAT

END

樣例輸出

64 13 4.9

144 51 2.8

方法一:

直接建立哈夫曼樹,然後求WPL。

方法二:

舉個栗子:ABBCCC

權值分別為1,2,3。

先把A,B,生成一個樹,此時A對應的編碼為0,B為1,ABB則為011,為三位長度,再把此樹和C合併的時候,A,B編碼長度都增加了1,此時A為00,B為01,ABB編碼長度增加的長度就是1+2(也就是第一次合併那個樹的權值)。

所以用這種思想可以不用去建哈夫曼樹,直接用優先佇列去存權值,每次把兩個最小的權值加起來(a+b),加在sum上,然後再把(a+b)壓入佇列。

方法二是參考的網上的解法,感覺不好想,或者是其他思想?反正法1也很直接。

#include<iostream>
#include<cstdlib>	
#include<cstdio>
#include<string>
#include<string.h>
#include<map>
#include<queue>
#include<algorithm>
#include<functional>
using namespace std;

typedef 
struct HufNode {
	int weight;
	struct HufNode* Left;
	struct HufNode* Right;
}*Huf;
struct cmp {
	bool operator()(Huf a, Huf b) {
		return a->weight > b->weight;
	}
};

int WPL(Huf T, int Depth)
{
	if ((!T->Left) && (!T->Right))
		return(Depth*(T->weight));
	else
		return (WPL(T->Left, Depth + 1) + WPL(T->Right, Depth + 1));
}
int main()
{
	string s;
	priority_queue< Huf, vector<Huf>, cmp>Q;
	while (cin >> s)
	{
		if (s == "END")break;
		int c[200];
		memset(c, 0, sizeof(c));
		for (int i = 0; i<s.size(); i++)
			c[s[i]]++;
		Huf H, T;
		for (int i = 0; i<200; i++)
			if (c[i])
			{
				H = (Huf)malloc(sizeof(struct HufNode));
				H->weight = c[i];
				H->Left = H->Right = NULL;
				Q.push(H);
				c[i] = 0;
			}
		
		int sum = 0;
		if (Q.size() == 1) { sum = s.size(); Q.pop(); }//只有一種字元。
		else {
			while (Q.size()>1)
			{
			    T = (Huf)malloc(sizeof(struct HufNode));
				T->Left = Q.top(); Q.pop();
				T->Right = Q.top(); Q.pop();
				T->weight = T->Left->weight + T->Right->weight;
				Q.push(T);
			}
			T = Q.top(); Q.pop();
			sum = WPL(T, 0);
		}
		printf("%d %d %.1f\n", 8 * s.size(), sum, (double)8.0 * s.size() / double(sum));
	}
	return 0;
}

#include<iostream>
#include<cstdlib>	
#include<cstdio>
#include<string>
#include<string.h>
#include<map>
#include<queue>
#include<algorithm>
#include<functional>
using namespace std;
int main()
{
	string s;
	priority_queue<int, vector<int>, greater<int>>Q;
	while (cin >> s)
	{
		if (s == "END")break;
		int c[200];
		memset(c, 0, sizeof(c));
		for (int i = 0; i<s.size(); i++)
			c[s[i]]++;
		for (int i = 0; i<200; i++)
			if (c[i])	
			{
				Q.push(c[i]);
				c[i] = 0;
			}

		int sum = 0;
		if (Q.size() == 1)sum = s.size();
		while (Q.size()>1)
		{
			int a = Q.top();
			Q.pop();
			int b = Q.top();
			Q.pop();
			sum += a + b;
			Q.push(a + b);

		}
		Q.pop();
		printf("%d %d %.1f\n", 8 * s.size(), sum, (double)8.0 * s.size() / double(sum));
	}
	return 0;
}