最优二叉树(哈夫曼树)、哈夫曼编码(HuffmanCoding)

 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 }

 

posted @ 2021-11-30 16:34  某科学的撒把豆子  阅读(45)  评论(0)    收藏  举报