POJ1521---哈夫曼編碼,求最優WPL
阿新 • • 發佈:2019-02-18
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; }