Huffman編碼, 題意:給你一個序列,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.
其實就是要你構造最優首碼樹, 也就是Huffman樹, 求它的帶權路徑和。 剛開始每種字元代表一個根節點, 它出現的次數就是其權值, 接下來就是求構造的Huffman樹的帶權路徑和了。
剛開始比較傻, 先建立了Huffman樹的二叉鏈表,然後通過先序遍曆求它的帶權路徑和。
code:
| 2496390 |
2010-05-28 12:34:39 |
Accepted |
1053 |
0MS |
256K |
1670 B |
G++ |
xwc-hdu |
#include <cstdio><br />#include <cstring><br />using namespace std;<br />char str[1010];<br />bool hash[1010];<br />int num[220];<br />typedef struct BitNode<br />{<br /> int data;<br /> BitNode *lchild, *rchild;<br /> BitNode()<br /> {<br /> lchild = NULL;<br /> rchild = NULL;<br /> }<br />}*BitTree;<br />BitTree T[1010];<br />int sum;<br />int Min(BitTree T[], int k)//求最小權值的根,返回根的下標<br />{<br /> int min, i;<br /> T[k] = new BitNode;<br /> T[k]->data = 0x3fffffff;<br /> min = k;<br /> for (i = 0; i < k; i++)<br /> {<br /> if (!hash[i] && T[i]->data < T[min]->data)<br /> min = i;<br /> }<br /> hash[min] = true;<br /> return min;<br />}<br />void Allsum(BitTree &T, int num)//先序求帶權路徑和<br />{<br /> if (T)<br /> {<br /> num++;//num表示該路徑上經過的節點個數<br /> if (!T->lchild && !T->rchild)<br /> {<br /> sum += (num - 1) * T->data;<br /> return ;<br /> }<br /> Allsum(T->lchild, num);<br /> Allsum(T->rchild, num);<br /> }<br />}<br />int main()<br />{<br /> int k, i, ans1;</p><p> while (scanf("%s", str) != EOF)<br /> {<br /> if (strcmp(str, "END") == 0)<br /> break;<br /> memset(num, 0, sizeof(num));<br /> memset(hash, false, sizeof(hash));<br /> for (i = 0; str[i]; i++)<br /> {<br /> num[str[i]]++;<br /> }<br /> k = 0;<br /> for (i = 0; i < 150; i++)<br /> {<br /> if (num[i] != 0)<br /> {<br /> T[k] = new BitNode;<br /> T[k++]->data = num[i];<br /> }<br /> }<br /> if (k == 1)//即表示只出現一個字元,最短編碼長度即字串長度<br /> {<br /> ans1 = strlen(str) * 8;<br /> sum = strlen(str);<br /> printf("%d %d %.1lf/n", ans1, sum, ans1 * 1.0/sum);<br /> continue;<br /> }<br /> int len = k;<br /> while (--len)<br /> {<br /> int tmp1 = Min(T, k);<br /> int tmp2 = Min(T, k);<br /> T[k] = new BitNode;<br /> T[k]->lchild = T[tmp1];<br /> T[k]->rchild = T[tmp2];<br /> T[k]->data = T[tmp1]->data + T[tmp2]->data;<br /> k++;<br /> }<br /> BitTree root = new BitNode;<br /> root = T[k-1];<br /> sum = 0;<br /> Allsum(root, 0);<br /> ans1 = strlen(str) * 8;<br /> printf("%d %d %.1lf/n", ans1, sum, ans1 * 1.0/sum);<br /> }<br /> return 0;<br />}
後來發現不用建樹的, 因為是求樹的帶權路徑長度, 根據權值可以直接求得。
#include <cstdio><br />#include <cstring><br />#include <queue><br />#include <vector><br />using namespace std;<br />int main()<br />{<br />char str[1010];<br />int i, test, k, nn, m, current, sum, num[150];<br />priority_queue<int, vector<int>, greater<int> >Q;</p><p>while (scanf("%s", str) != EOF)<br />{<br />if (strcmp(str, "END") == 0)<br />break;<br />while (!Q.empty())<br />Q.pop();<br />memset(num, 0, sizeof(num));<br />for (i = 0; str[i]; i++)<br />{<br />num[str[i]]++;<br />}<br />k = 0;<br />for (i = 'A'; i <= 'Z'; i++)<br />{<br />if (num[i] != 0)<br />{<br />Q.push(num[i]);<br />k++;<br />}<br />}<br />if (num['_'] != 0)<br />{<br />Q.push(num['_']);<br /> k++;<br />}<br />nn = k;<br />sum = 0;<br />while (--k)<br />{<br />current = Q.top();<br />Q.pop();<br />current += Q.top();<br />Q.pop();<br />sum += current;<br />Q.push(current);<br />}<br />if (nn == 1)<br />sum = strlen(str);<br />int ans1 = strlen(str) * 8;<br />printf("%d %d %.1lf/n", ans1, sum, ans1 * 1.0/sum);<br />}<br />return 0;<br />}