1 //求哈夫曼编码的算法如下所示:
2 //-----哈夫曼树和哈夫曼编码的存储表示-----
3 typedef struct{
4 unsigned int weight;
5 unsigned int parent,lchild,rchild;
6 }HTNode,*HuffmanTree;
7 typedef char * * HuffmanCode;
8 //-----求哈夫曼编码的算法如下所示-----
9 void HuffmanCoding(HuffmanTree & HT, HuffmanCode &HC, int *w, int n){
10 //w存放n个自负字符的权值(均>0),构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC
11 if(n <= 1) return;
12 m = 2 * n - 1;
13 HT = (HuffmanTree)malloc((m + 1) * sizeof(HTNode));
14 for(p = HT + 1, i = 1; i <= n; ++i, ++p, ++w) *p = {*w,0,0,0};
15 for(; i <= m; ++i,++p) *p = {0,0,0,0};
16 for(i = n+1; i <= m; ++i){ //建哈夫曼树
17 //在HT[1..i-1]选择parent为0且weight最小的两个结点,其序号分别为s1和s2.
18 Select(HT,i-1,s1,s2);
19 HT[s1].parent = i; HT[s2].parent = i;
20 HT[i].lchild = s1; HT[i.rchild = s2;
21 HT[i].weight = HT[sl].weight + HT[s2].weight;
22 }
23 //---从叶子到根逆向求每个字符的哈夫曼编码
24 HC = (HuffmanCode)malloc((n + 1) * sizeof(char *)); //分配n个字符编码的头指针位置
25 cd = (char *)malloc(n * sizeof(char)); //分配求编码的工作空间
26 cd[n-1] = "\0"; //编码结束符
27 for(i=1; i <= n; ++i){ //逐个字符求哈夫曼编码
28 start = n-1; //编码结束符位置
29 for(c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent)//从叶子到根逆向求编码
30 if(HT[f].lchild == c) cd[--start] = '0';
31 else cd[--start] = "1";
32 HC[i] = (char *)malloc((n - start) * sizeof(char));//为敌第i个字符编码分配空间
33 strcpy(HC[i],&cd[start]); //把cd复制到HC
34 }
35 free(cd); //释放工作空间
36 //---无栈非递归变里哈夫曼树,求哈夫曼编码
37 HC = (HuffmanCode)malloc((n + 1) * sizeof(char *));
38 p = m; cdlen = 0;
39 for(i = 1; i <= m; ++i) HT[i].weight = 0; //遍历哈夫曼树时用作结点状态标志
40 while(p){
41 if(HT[p].weight == 0){ //向左
42 HT[p].weight = 1;
43 if(HT[p].lchild != 0) {P = HT[P].lchild; cd[cdlen++] = "0";}
44 else if(HT[p].rchild == 0){ //登记叶子结点的字符的编码
45 HC[p] = (char *)malloc((cd + 1) * sizeof (char));
46 cd[cdlen] = "\0"; strcpy(HC[p],cd);//复制编码(串)
47 }//else if
48 }//if
49 else if(HT[p].weight == 1){ //向右
50 HT[p].weight = 2;
51 if(HT[p].lchild != 0) {p = HT[p].lchild; cd[cdlen++] = "1";}
52 }else{ //HT[p].weight == 2,退回
53 HT[p].weight = 0; p = HT[p].parent; --cdlen; //遇到父节点,编码长度减1
54 }//else
55 }//while
56 }