第十周项目二 哈夫曼树

  1. 烟台大学计算机学院  
  2.   
  3. 作者:王雪行
  4.   
  5. 问题描述:哈夫曼编码的算法验证 
  6.   
  7. 输入描述:无 
  8.   
  9. 输出描述:哈夫曼编码结果,平均长度 
  10.  
  11.   
  12. */   
  13.   
  14.   
  15.   
  16. #include <stdio.h>  
  17. #include <string.h>  
  18.   
  19. #define N 50        //叶子结点数  
  20. #define M 2*N-1     //树中结点总数  
  21.   
  22. //哈夫曼树的节点结构类型  
  23. typedef struct  
  24. {  
  25.     char data;  //结点值  
  26.     double weight;  //权重  
  27.     int parent;     //双亲结点  
  28.     int lchild;     //左孩子结点  
  29.     int rchild;     //右孩子结点  
  30. } HTNode;  
  31.   
  32. //每个节点哈夫曼编码的结构类型  
  33. typedef struct  
  34. {  
  35.     char cd[N]; //存放哈夫曼码  
  36.     int start;  
  37. } HCode;  
  38.   
  39. //构造哈夫曼树  
  40. void CreateHT(HTNode ht[],int n)  
  41. {  
  42.     int i,k,lnode,rnode;  
  43.     double min1,min2;  
  44.     for (i=0; i<2*n-1; i++)         //所有结点的相关域置初值-1  
  45.         ht[i].parent=ht[i].lchild=ht[i].rchild=-1;  
  46.     for (i=n; i<2*n-1; i++)         //构造哈夫曼树  
  47.     {  
  48.         min1=min2=32767;            //lnode和rnode为最小权重的两个结点位置  
  49.         lnode=rnode=-1;  
  50.         for (k=0; k<=i-1; k++)  
  51.             if (ht[k].parent==-1)   //只在尚未构造二叉树的结点中查找  
  52.             {  
  53.                 if (ht[k].weight<min1)  
  54.                 {  
  55.                     min2=min1;  
  56.                     rnode=lnode;  
  57.                     min1=ht[k].weight;  
  58.                     lnode=k;  
  59.                 }  
  60.                 else if (ht[k].weight<min2)  
  61.                 {  
  62.                     min2=ht[k].weight;  
  63.                     rnode=k;  
  64.                 }  
  65.             }  
  66.         ht[i].weight=ht[lnode].weight+ht[rnode].weight;  
  67.         ht[i].lchild=lnode;  
  68.         ht[i].rchild=rnode;  
  69.         ht[lnode].parent=i;  
  70.         ht[rnode].parent=i;  
  71.     }  
  72. }  
  73.   
  74. //实现哈夫曼编码  
  75. void CreateHCode(HTNode ht[],HCode hcd[],int n)  
  76. {  
  77.     int i,f,c;  
  78.     HCode hc;  
  79.     for (i=0; i<n; i++) //根据哈夫曼树求哈夫曼编码  
  80.     {  
  81.         hc.start=n;  
  82.         c=i;  
  83.         f=ht[i].parent;  
  84.         while (f!=-1)   //循序直到树根结点  
  85.         {  
  86.             if (ht[f].lchild==c)    //处理左孩子结点  
  87.                 hc.cd[hc.start--]='0';  
  88.             else                    //处理右孩子结点  
  89.                 hc.cd[hc.start--]='1';  
  90.             c=f;  
  91.             f=ht[f].parent;  
  92.         }  
  93.         hc.start++;     //start指向哈夫曼编码最开始字符  
  94.         hcd[i]=hc;  
  95.     }  
  96. }  
  97.   
  98. //输出哈夫曼编码  
  99. void DispHCode(HTNode ht[],HCode hcd[],int n)  
  100. {  
  101.     int i,k;  
  102.     double sum=0,m=0;  
  103.     int j;  
  104.     printf("  输出哈夫曼编码:\n"); //输出哈夫曼编码  
  105.     for (i=0; i<n; i++)  
  106.     {  
  107.         j=0;  
  108.         printf("      %c:\t",ht[i].data);  
  109.         for (k=hcd[i].start; k<=n; k++)  
  110.         {  
  111.             printf("%c",hcd[i].cd[k]);  
  112.             j++;  
  113.         }  
  114.         m+=ht[i].weight;  
  115.         sum+=ht[i].weight*j;  
  116.         printf("\n");  
  117.     }  
  118.     printf("\n  平均长度=%g\n",1.0*sum/m);  
  119. }  
  120.   
  121. int main()  
  122. {  
  123.     int n=8,i;      //n表示初始字符串的个数  
  124.     char str[]= {'a''b''c''d''e''f''g''h'};  
  125.     double fnum[]= {0.07,0.19,0.02,0.06,0.32,0.03,0.21,0.1};  
  126.     HTNode ht[M];  
  127.     HCode hcd[N];  
  128.     for (i=0; i<n; i++)  
  129.     {  
  130.         ht[i].data=str[i];  
  131.         ht[i].weight=fnum[i];  
  132.     }  
  133.     printf("\n");  
  134.     CreateHT(ht,n);  
  135.     CreateHCode(ht,hcd,n);  
  136.     DispHCode(ht,hcd,n);  
  137.     printf("\n");  
  138.     return 0;  
  139. }  

运行结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值