现在的位置: 首页 > 综合 > 正文

赫夫曼编程C语言实现

2012年12月16日 ⁄ 综合 ⁄ 共 5793字 ⁄ 字号 评论关闭

问题描述】
    利用Huffman编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接受端将传来的数据编码进行译码(复原)。对于有些信道,每端都需要一个完整的编/译码系统。试为这样的信息收发站编写一个Huffman的编/译码系统。给定一组权值{7,9,5,6,10,1,13,15,4,8},构造一棵赫夫曼树,并计算带权路径长度WPL。

 【数据描述】

//- - - - - 赫夫曼树的存储表示 - - - - -

typedef struct {

   unsigned int weight;

   unsigned int parent,lchild,rchild;

}HTNode;    //用顺序存储结构表示赫夫曼树的结点结构定义

//动态分配数组存储Huffman编码表

算法描述】

1.初始化:从键盘读入n个字符,以及它们的权值,建立Huffman树
2.编码:根据建立的Huffman树,求每个字符的Huffman编码。对给定的待编码字符序列进行编码。
3.译码:利用已经建立好的Huffman树,对上面的编码结果译码。译码的过程是分解电文中的字符串,从根结点出发,按字符’0’和’1’确定找左孩子或右孩子,直至叶结点,便求得该子串相应的字符。
4.打印 Huffman树。

【C源程序】
/*实现初始化,建立Huffman树,并完成字符的编码*/

#include <stdio.h>

#define N 10     /*待编码字符的个数,即树中叶结点的最大个数*/

#define M 2*N-1  /*树中总的结点数目*/

typedef struct{

  unsigned int weight;

  unsigned int parent,lchild,rchild;

  }HTNode;  /*树中结点的结构*/

typedef struct {

  char data;     /*待编码的字符*/

  int weight;    /*字符的权值  */

  char code[N];  /*字符的编码 */

} HTCode;

void Init(HTCode hc[],int *n){

  /*初始化,读入待编码字符的个数n,从键盘输入n个字符和n个权值*/

int i;

  printf("/ninput n=");

  scanf("%d",&(*n));

  printf("/ninput %d character/n",*n);

  for (i=1;i<=*n;i++) hc[i].data=getch();

  printf("/ninput %d weight/n",*n);

  for (i=1;i<=*n;i++) scanf("%d",&(hc[i].weight));

}

void Select(HTNode ht[],int k,int *s1,int *s2){

/*ht[1…k]中选择parent为0,并且weight最小的两个结点

其序号由指针变量s1,s2指向*/

  int i;

  for (i=1;i<=k && ht[i].parent!=0 ;i++);

  *s1=i;

  for (i=1;i<=k;i++)

    if (ht[i].parent==0 && ht[i].weight<ht[*s1].weight) *s1=i;

  for (i=1; i<=k ; i++)

    if (ht[i].parent==0 && i!=*s1) break;

  *s2=i;

  for (i=1;i<=k;i++)

    if ( ht[i].parent==0 && i!=*s1 && ht[i].weight<ht[*s2].weight) *s2=i;

}

void HuffmanCoding(HTNode ht[],HTCode hc[],int n){

/*构造Huffman树ht,并求出n个字符的编码*/

  char cd[N];

  int i,j,m,c,f,s1,s2,start;

  m=2*n-1;

  for (i=1;i<=m;i++){

   if (i<=n)  ht[i].weight=hc[i].weight;

   else ht[i].weight=0;

   ht[i].parent=ht[i].lchild=ht[i].rchild=0;

   }

 for (i=n+1;i<=m;i++){

    Select(ht,i-1,&s1,&s2);

    ht[s1].parent=i;   ht[s2].parent=i;

    ht[i].lchild=s1;   ht[i].rchild=s2;

    ht[i].weight=ht[s1].weight+ht[s2].weight;

  }

  cd[n-1]='/0';

  for (i=1;i<=n;i++) {

    start=n-1;

    for (c=i,f=ht[i].parent;f;c=f,f=ht[f].parent)

      if (ht[f].lchild==c) cd[--start]='0';

      else cd[--start]='1';

    strcpy(hc[i].code,&cd[start]);

  }

}

main(){

 int i,m,n,w[N+1];

 HTNode ht[M+1];

 HTCode hc[N+1];

 Init(hc,&n);           /*初始化*/

 HuffmanCoding(ht,hc,n);/*构造Huffman树,并形成字符的编码*/

/*输出字符的编码*/

 for (i=1;i<=n;i++)printf("/n%c --- %s",hc[i].data,hc[i].code);

}

【测试数据】

1. 根据运行提示,依次输入待编码的字符个数和这些字符,以及每个字符的权值:

input n=4↙

input 4character       

abcd↙

input4 weight       

7 5 2 4↙

        输出:

        a --- 0

        b --- 10

        c --- 110

        d --- 111

2.可根据运行提示,自行指定数据,观察程序的运行结果。

【说明】
    此处只是Huffman树的建立和编码算法的实现,一个完整的Huffman编/译码系统应进一步完善,实现以上算法描述的四个基本要求,并可考虑将Hufmman树和Huffman编码存在磁盘文件中

下面的方法没有说明,不过可以直接运行!

#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>

typedef struct

{

         int weight;

         char ch;

         int parent,lchild,rchild;

}HTNode,*HuffmanTree;

typedef struct

{

 char ch;
 char *chs;

}HuffmanCode;

typedef struct

{

 char ch;
 int weight;

}sw;

typedef struct

{

 HuffmanTree HT;
 HuffmanCode *HC;

}huf;

void select(HTNode * HT,int n,int *n1,int *n2)

{

         int i=1;
   int n3;

         while(HT[i].parent!=0)

         i++;

         *n1=i;

          i++;

         while(HT[i].parent!=0)         i++;

         *n2=i;

         if(HT[*n1].weight<HT[*n2].weight)

         {         n3=*n1;*n1=*n2;*n2=n3;}

         for(i++;i<=n;i++)

         {

           if(HT[i].parent==0)

           {         if(HT[i].weight<HT[*n1].weight)

         *n1=i;

              else if(HT[i].weight<HT[*n2].weight)

         *n2=i;

           }

         }

}

huf * HuffmanCoding(HuffmanTree HT,HuffmanCode *HC,sw *w,int n,huf *HUF)

{
 int m,i,s1,s2,start,c,f;

HuffmanTree p;

char *cd;

if(n<=1) return 0;

m=2*n-1;

HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));

for(p=HT+1,i=1;i<=n;i++,p++,w++)

{p->weight=w->weight;p->ch=w->ch;p->parent=0;p->lchild=0;p->rchild=0;}

for(;i<=m;i++,p++)

{p->weight=0;p->ch='^';p->parent=0;p->lchild=0;p->rchild=0;}

for(i=n+1;i<=m;i++)

{

           select(HT,i-1,&s1,&s2);

           HT[s1].parent=i;HT[s2].parent=i;

           HT[i].lchild=s1;HT[i].rchild=s2;

           HT[i].weight=HT[s1].weight+HT[s2].weight;

}

HC=(HuffmanCode *)malloc((n+1)*sizeof(char));

cd=(char *)malloc(n*sizeof(char));

cd[n-1]='\0';

for(i=1;i<=n;i++)

{         start=n-1;

           for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)

           if(HT[f].lchild==c)cd[--start]='0';

           else cd[--start]='1';

           HC[i].ch=HT[i].ch;

           HC[i].chs=(char*)malloc((n-start)*sizeof(char));

           strcpy(HC[i].chs,&cd[start]);

           printf("%c %-10s\n",HC[i].ch,HC[i].chs);

}

HUF->HT=HT;

HUF->HC=HC;

return HUF;

}

char *       convert(char *chars,char *chars1,HuffmanCode *hc,int n)

{

        char *p=chars; int i;

        strcpy(chars1,"");

        while(*p)

        {

          i=1;        while(hc[i].ch!=*p&&i<=n)        i++;

          strcat(chars1,hc[i].chs);        p++;

        }

printf("the chars translate are:%s\n",chars1);

return chars1;

}

void transcode(HuffmanTree ht,char *chars2,char*chars3)

{

        int i=1,p; char *q=chars2;char *r=chars3;

        while(ht[i].parent!=0)        i++;

         p=i;

        while(*q)

        {

          while(ht[p].lchild!=0 && *q)

          {

            if(*q=='0')

         p=ht[p].lchild;

            else p=ht[p].rchild;

            q++;

          }

          if(ht[p].lchild==0)

{*r=ht[p].ch;r++;}

          p=i;

        }

        *r='\0';

        printf("the chars are:");

        puts(chars3);

}

void input(int *n,sw *w)

{

         int i;

printf("input the count of char:");   /*输入字符的数目*/

scanf("%d",n);

    

for(i=1;i<=*n;i++,w++)

{printf("input the %dth char and weight:",i); /*输入每个节点的字符和出现的次数*/

fflush(stdin);

scanf("%c%d",&w->ch,&w->weight);

}

}

void main()

{HTNode HT;

HuffmanCode HC,*hc;

HuffmanTree ht;

huf *HUF,huf2;

int n;

sw w[40];

char ch,inchar[500],outchar[1000];

char *abc;

char *p=inchar;

input(&n,w);

HUF=HuffmanCoding(&HT,&HC,w,n,&huf2);

printf("input chars to translate and end with '#':");

fflush(stdin);/*清除流,解决输入干扰*/

ch=getchar();

while(ch!='#')

{*p=ch;

p++;

ch=getchar();

}

*p='\0';

hc=HUF->HC;

ht=HUF->HT;

abc=convert(inchar,outchar,hc,n);

transcode(ht,abc,outchar);

getchar();

getchar();

}
 

抱歉!评论已关闭.