哈夫曼树又称最优树,是一类带权路径长度最短的树。在本例中我们用它对字符进行编码。首先先创建一个哈夫曼树,然后从叶子节点开始往根上寻找路线,是左子树则编码为0,右子树编码为1. 有一个步骤我们需要将最小的两个权值的叶子结点合并成一个节点,同时还要删除这两个节点,我用的是优先队列,优先队列出来的是权值最小的点,我们把他们合并之后可以很容易的删除。同时要注意哈夫曼树并不唯一,但是他们都具有最小的WPL(树的带权路径长度)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| #include <bits/stdc++.h> using namespace std; typedef struct Tnode{ int w; int pos; int parent,lchild,rchild; bool operator<(const Tnode &a)const { return a.w < w; } }Tnode,*tree; int n; priority_queue<Tnode>P; string s[100]; void select(tree &HT,int &s1, int &s2) { Tnode t = P.top(); s1 = t.pos; P.pop(); t = P.top(); s2 = t.pos; P.pop(); } void huffmantree(tree &HT) { int m = 2 * n - 1; int s1,s2; HT = new Tnode[100]; for(int i = 1; i <= m ;++i) { HT[i].parent = HT[i].lchild = HT[i].rchild = 0; } for(int i = 1; i <= n; ++i) { cin >> HT[i].w; HT[i].pos = i; P.push(HT[i]); } for(int i = n + 1; i <= m ;++i) { select(HT ,s1, s2); HT[s1].parent = i; HT[s2].parent = i; HT[i].lchild = s1; HT[i].rchild = s2; HT[i].w = HT[s1].w + HT[s2].w; HT[i].pos = i ; P.push(HT[i]); } } void huffmancode(tree &HT) { for(int i = 1; i <= n; ++i) { int index = i; int p = HT[i].parent; while(p) { if(HT[p].lchild == index) s[i] += '0'; else s[i] += '1'; index = p; p = HT[p].parent; } reverse(s[i].begin(),s[i].end()); } } int main() { tree HT; cin >> n; huffmantree(HT); huffmancode(HT); for(int i = 1; i <= n; ++i) { cout << "第" << i << "个字符的权值为:" << HT[i].w << endl; cout << "第" << i << "个字符的哈夫曼编码为:" << endl; cout << s[i] << endl; } }
|