zl程序教程

您现在的位置是:首页 >  其他

当前栏目

哈夫曼的c语言实现代码

语言代码 实现 哈夫曼
2023-06-13 09:15:03 时间

我们设置一个结构数组HuffNode保存哈夫曼树中各结点的信息。根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1。HuffNode结构中有weight,lchild,rchild和parent域。其中,weight域保存结点的权值,lchild和rchild分别保存该结点的左、右孩子的结点在数组HuffNode中的序号,从而建立起结点之间的关系。为了判定一个结点是否已加入到要建立的哈夫曼树中,可通过parent域的值来确定。初始时parent的值为-1。当结点加入到树中去时,该结点parent的值为其父结点在数组HuffNode中的序号,而不会是-1了。

求叶结点的编码:
该过程实质上就是在已建立的哈夫曼树中,从叶结点开始,沿结点的双亲链域回退到根结点,每回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值。由于一个字符的哈夫曼编码是从根结点到相应叶结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位,后得到的分支代码为所求编码的高位码。我们可以设置一个结构数组HuffCode用来存放各字符的哈夫曼编码信息,数组元素的结构中有两个域:bit和start。其中,域bit为一维数组,用来保存字符的哈夫曼编码,start表示该编码在数组bit中的开始位置。所以,对于第i个字符,它的哈夫曼编码存放在HuffCode[i].bit中的从HuffCode[i].start到n的bit位中。

复制代码代码如下:

/*-------------------------------------------------------------------------
 *Name:  哈夫曼编码源代码。
 *在Win-TC下测试通过
 *实现过程:着先通过HuffmanTree()函数构造哈夫曼树,然后在主函数main()中
 *          自底向上开始(也就是从数组序号为零的结点开始)向上层层判断,若在
 *          父结点左侧,则置码为0,若在右侧,则置码为1。最后输出生成的编码。
 *------------------------------------------------------------------------*/
#include<stdio.h>

#defineMAXBIT     100
#defineMAXVALUE 10000
#defineMAXLEAF    30
#defineMAXNODE   MAXLEAF*2-1

typedefstruct
{
   intbit[MAXBIT];
   intstart;
}HCodeType;       /*编码结构体*/
typedefstruct
{
   intweight;
   intparent;
   intlchild;
   intrchild;
}HNodeType;       /*结点结构体*/

/*构造一颗哈夫曼树*/
voidHuffmanTree(HNodeTypeHuffNode[MAXNODE], intn)
{
   /*i、j:循环变量,m1、m2:构造哈夫曼树不同过程中两个最小权值结点的权值,
       x1、x2:构造哈夫曼树不同过程中两个最小权值结点在数组中的序号。*/
   inti,j,m1,m2,x1,x2;
   /*初始化存放哈夫曼树数组HuffNode[]中的结点*/
   for(i=0;i<2*n-1;i++)
   {
       HuffNode[i].weight=0;
       HuffNode[i].parent=-1;
       HuffNode[i].lchild=-1;
       HuffNode[i].lchild=-1;
   }/*endfor*/

   /*输入n个叶子结点的权值*/
   for(i=0;i<n;i++)
   {
       printf("Pleaseinputweightofleafnode%d:\n",i);
       scanf("%d",&HuffNode[i].weight);
   }/*endfor*/

   /*循环构造Huffman树*/
   for(i=0;i<n-1;i++)
   {
       m1=m2=MAXVALUE;    /*m1、m2中存放两个无父结点且结点权值最小的两个结点*/
       x1=x2=0;
       /*找出所有结点中权值最小、无父结点的两个结点,并合并之为一颗二叉树*/
       for(j=0;j<n+i;j++)
       {
           if(HuffNode[j].weight<m1&&HuffNode[j].parent==-1)
           {
               m2=m1;
               x2=x1;
               m1=HuffNode[j].weight;
               x1=j;
           }
           elseif(HuffNode[j].weight<m2&&HuffNode[j].parent==-1)
           {
               m2=HuffNode[j].weight;
               x2=j;
           }
       }/*endfor*/
           /*设置找到的两个子结点x1、x2的父结点信息*/
       HuffNode[x1].parent =n+i;
       HuffNode[x2].parent =n+i;
       HuffNode[n+i].weight=HuffNode[x1].weight+HuffNode[x2].weight;
       HuffNode[n+i].lchild=x1;
       HuffNode[n+i].rchild=x2;

       printf("x1.weightandx2.weightinround%d:%d,%d\n",i+1,HuffNode[x1].weight,HuffNode[x2].weight); /*用于测试*/
       printf("\n");
   }/*endfor*/
}/*endHuffmanTree*/

intmain(void)
{
   HNodeTypeHuffNode[MAXNODE];           /*定义一个结点结构体数组*/
   HCodeTypeHuffCode[MAXLEAF], cd;      /*定义一个编码结构体数组,同时定义一个临时变量来存放求解编码时的信息*/
   inti,j,c,p,n;
   printf("Pleaseinputn:\n");
   scanf("%d",&n);
   HuffmanTree(HuffNode,n);

   for(i=0;i<n;i++)
   {
       cd.start=n-1;
       c=i;
       p=HuffNode[c].parent;
       while(p!=-1)  /*父结点存在*/
       {
           if(HuffNode[p].lchild==c)
               cd.bit[cd.start]=0;
           else
               cd.bit[cd.start]=1;
           cd.start--;       /*求编码的低一位*/
           c=p;                   
           p=HuffNode[c].parent;   /*设置下一循环条件*/
       }/*endwhile*/

       /*保存求出的每个叶结点的哈夫曼编码和编码的起始位*/
       for(j=cd.start+1;j<n;j++)
       {HuffCode[i].bit[j]=cd.bit[j];}
       HuffCode[i].start=cd.start;
   }/*endfor*/

   /*输出已保存好的所有存在编码的哈夫曼编码*/
   for(i=0;i<n;i++)
   {
       printf("%d"sHuffmancodeis:",i);
       for(j=HuffCode[i].start+1;j<n;j++)
       {
           printf("%d",HuffCode[i].bit[j]);
       }
       printf("\n");
   }
   getch();
   return0;
}