(1.2.5.7)哈弗曼树=最优二叉树

(q)根据哈弗曼树的定义,一棵二叉树要使其WPL值最小,必须使权值越大的叶子结点越靠近根结点,而权值越小的叶子结点 越远离根结点。
哈弗曼依据这一特点提出了一种构造最优二叉树的方法,其基本思想如下:
 
下面演示了用Huffman算法构造一棵Huffman树的过程:
(2)例题:
假设一个文本文件TFile中只包含7个字符{A,B,C,D,E,F,G},这7个字符在文本中出现的次数为{5,24,7,17,34,5,13}
利用哈夫曼树可以为文件TFile构造出符合前缀编码要求的不等长编码
 
具体做法:
1. 将TFile中7个字符都作为叶子结点,每个字符出现次数作为该叶子结点的权值
2. 规定哈夫曼树中所有左分支表示字符0,所有右分支表示字符1,将依次从根结点到每个叶子结点所经过的分支的二进制位的序列作为该
     结点对应的字符编码
3. 由于从根结点到任何一个叶子结点都不可能经过其他叶子,这种编码一定是前缀编码,哈夫曼树的带权路径长度正好是文件TFile编码 的总长度
通过哈夫曼树来构造的编码称为哈弗曼编码(huffman code)
 
 
  .
(3)结构与创建
  1. class HTNode{        // 树中结点的结构  
  2. public:   
  3.     unsigned int weight;  
  4.     unsigned int parent,lchild,rchild;  
  5. };                      
  6.   
  7. class HTCode{  
  8. public:  
  9.     char data;      // 待编码的字符  
  10.     int weight;     // 字符的权值  
  11.     char code[N];   // 字符的编码  
  12. };  
  13.   
  14. void Init(HTCode hc[], int *n){  
  15. // 初始化,读入待编码字符的个数n,从键盘输入n个字符和n个权值  
  16.     int i;  
  17.     printf("input n = ");  
  18.     scanf("%d",&(*n));  
  19.   
  20.     printf("\ninput %d character\n",*n);  
  21.       
  22.     fflush(stdin);  
  23.     for(i=1; i<=*n; ++i)  
  24.         scanf("%c",&hc[i].data);  
  25.   
  26.     printf("\ninput %d weight\n",*n);  
  27.       
  28.     for(i=1; i<=*n; ++i)  
  29.         scanf("%d",&(hc[i].weight) );  
  30.     fflush(stdin);  
  31. }//  
  32.   
  33. void Select(HTNode ht[], int k, int *s1, int *s2){  
  34. // ht[1...k]中选择parent为0,并且weight最小的两个结点,其序号由指针变量s1,s2指示  
  35.     int i;  
  36.     for(i=1; i<=k && ht[i].parent != 0; ++i){   
  37.         ; ;  
  38.     }  
  39.     *s1 = i;  
  40.   
  41.     for(i=1; i<=k; ++i){  
  42.         if(ht[i].parent==0 && ht[i].weight<ht[*s1].weight)  
  43.             *s1 = i;  
  44.     }  
  45.   
  46.     for(i=1; i<=k; ++i){  
  47.         if(ht[i].parent==0 && i!=*s1)  
  48.             break;  
  49.     }  
  50.     *s2 = i;  
  51.   
  52.     for(i=1; i<=k; ++i){  
  53.         if(ht[i].parent==0 && i!=*s1 && ht[i].weight<ht[*s2].weight)  
  54.             *s2 = i;  
  55.     }  
  56. }  
  57.   
  58. void HuffmanCoding(HTNode ht[],HTCode hc[],int n){  
  59. // 构造Huffman树ht,并求出n个字符的编码  
  60.     char cd[N];  
  61.     int i,j,m,c,f,s1,s2,start;  
  62.     m = 2*n-1;  
  63.       
  64.     for(i=1; i<=m; ++i){  //初始化操作,全部置0
  65.         if(i <= n)  
  66.             ht[i].weight = hc[i].weight;  
  67.         else  
  68.             ht[i].parent = 0;  
  69.         ht[i].parent = ht[i].lchild = ht[i].rchild = 0;  
  70.     }  
  71.   
  72.     for(i=n+1; i<=m; ++i){  
  73.         Select(ht, i-1, &s1, &s2);  
  74.         ht[s1].parent = i;  
  75.         ht[s2].parent = i;  
  76.         ht[i].lchild = s1;  
  77.         ht[i].rchild = s2;  
  78.         ht[i].weight = ht[s1].weight+ht[s2].weight;  
  79.     }  
  80.   
  81.     cd[n-1] = '\0';  
  82.   
  83.     for(i=1; i<=n; ++i){  
  84.         start = n-1;  
  85.         for(c=i,f=ht[i].parent; f; c=f,f=ht[f].parent){  
  86.             if(ht[f].lchild == c)  
  87.                 cd[--start] = '0';  
  88.             else  
  89.                 cd[--start] = '1';  
  90.         }  
  91.         strcpy(hc[i].code, &cd[start]);  
  92.     }  
  93. }  
  94.   
  95.   
  96. int main()  
  97. {  
  98.     int i,m,n,w[N+1];  
  99.     HTNode ht[M+1];  
  100.     HTCode hc[N+1];  
  101.     Init(hc, &n);     // 初始化  
  102.     HuffmanCoding(ht,hc,n);   // 构造Huffman树,并形成字符的编码  
  103.   
  104.     for(i=1; i<=n; ++i)    
  105.         printf("\n%c---%s",hc[i].data,hc[i].code);    
  106.     printf("\n");  
  107.   
  108.     return 0;  
  109. }  

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值