刚刚完成的HuffmanCode问题

最近的信息编码作业。写了个HuffmanCode的程序(C)

#include<math.h>
#define maxvalue 10000.0
typedef struct{    /*哈夫曼树的存储表示方法*/
   float weight;   /* 权重,即概率 */
   int parent,lchild,rchild;   /*每个结点均有父结点,左孩子,右孩子*/
}HTNode,*HuffmanTree;
typedef char **HuffmanCode;   /*双重指针存储哈夫曼编码*/

/*哈夫曼编码的算法*/
void HuffmanCoding(float *w,int n){
   HuffmanTree HT;
   HuffmanCode HC;
   int m,i,j;
   float m1,m2;
   int x1,x2,c; /*x1代表左孩子的序号,x2代表右孩子的序号*/
   char *cd;
   int f,start;
   float hx=0.0,hn=0.0,t;   /*信源熵,平均编码长度,编码效率*/
   if(n<=1)return;
   m=2*n-1;        /*哈夫曼树的总结点数*/
   /*开始构造一棵哈夫曼树*/
   HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
   /*赋初值*/
   for(i=0;i<n;i++){
      HT[i].weight=w[i];
      HT[i].parent=-1;
      HT[i].lchild=-1;
      HT[i].rchild=-1;
   }
   for(;i<m;i++){
      HT[i].weight=0;
      HT[i].parent=-1;
      HT[i].lchild=-1;
      HT[i].rchild=-1;
   }
   /*寻找每个结点的父结点,左孩子,右孩子*/
   for(i=0;i<n-1;i++){
      m1=m2=maxvalue;
      x1=x2=0;
      for(j=0;j<n+i;j++){   /* 左孩子为权重最小的数*/
         if(HT[j].weight<m1 && HT[j].parent==-1){
            m2=m1;
            x2=x1;
            m1=HT[j].weight;
            x1=j;
         }
         /*右孩子为权重次小的数*/
         else if(HT[j].weight<m2 && HT[j].parent==-1){
            m2=HT[j].weight;
            x2=j;
         }
      }
      HT[x1].parent=n+i;
      HT[x2].parent=n+i;
      HT[n+i].weight=HT[x1].weight+HT[x2].weight;
      HT[n+i].lchild=x1;
      HT[n+i].rchild=x2;
   }
   /*从叶子结点开始,逆向求编码*/
   printf("/nHuffmanCode:/n");
   HC=(HuffmanCode)malloc(n*sizeof(char *)); /*存储所有概率的编码*/
   cd=(char *)malloc(n*sizeof(char));  /*暂时存储每个概率的编码*/
   cd[n-1]='/0'; /*字符数组最后一位置字符串结束标志*/
   for(i=0;i<n;i++){
      start=n-1;
      /*逆向查找,直至根结点*/
      for(c=i,f=HT[i].parent;f!=-1;c=f,f=HT[f].parent){
         if(HT[f].lchild==c) cd[--start]='0'; /*若是左孩子,置0*/
         else  cd[--start]='1';  /*若是右孩子,则置1*/
      }
      /*根据实际编码长度动态开辟存放每个概率编码的数组*/
      HC[i]=(char *)malloc((n-start)*sizeof(char));
      strcpy(HC[i],&cd[start]);
   }
   free(cd); /*释放空间*/
   /*输出哈夫曼编码,并求信源熵、平均编码长度*/
   for(i=0;i<n;i++){
      printf("%s/t",HC[i]);
      hx+=(-HT[i].weight*log10(HT[i].weight))/0.30103;
      hn+=strlen(HC[i])*HT[i].weight;
   }
   t=hx/hn;  /*求编码效率*/
   printf("/n信源熵:H(X)=%.3f/n编码的平均码长:%.3f/n编码效率:%.3f",hx,hn,t);
}

/*主函数*/
main(){
   float *w,sum;
   int n,i;
   do{  /*输入概率个数n,必须是大于0的整数*/
      printf("/nthe number n(>1):");
      scanf("%d",&n);
   }while(n<=1);
   w=&sum;
   w=(float *)malloc(n*sizeof(float));
   /*输入概率,总和必须为1.0*/
   do{
      printf("every weight(sum=1.0):/n");
      sum=0.0;
      for(i=0;i<n;i++){
         scanf("%f",&w[i]);
         sum+=w[i];
      }
   }while(sum!=1.000000);
   /*调用哈夫曼编码函数*/
   HuffmanCoding(w,n);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值