赫夫曼编码/译码器

来源:互联网 发布:贴面膜后要洗脸吗 知乎 编辑:程序博客网 时间:2024/05/01 13:04

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

#define NULL 0
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define MAX_NUM 10000
#define MAX 60

typedef int Status;
typedef char **HuffmanCode;

typedef struct{
    unsigned int   weight;
    unsigned int   parent,lchild,rchild;
}HTNode,*HuffmanTree;

typedef struct{
    HuffmanTree HT;
    char        *c;
    int         longth;
    HuffmanCode HC;
}Huffman;

void Select(HuffmanTree HT,int end,int *s1,int *s2)
{
  int i;
  int min1=MAX_NUM;
  int min2;
  for (i=1;i<=end;i++)
  {
    if (HT[i].parent==0&&HT[i].weight<min1)
    {
      *s1=i;
      min1=HT[i].weight;
    }
  }
  min2=MAX_NUM;
  for(i=1;i<=end;i++)
  {
    if(HT[i].parent==0&&(*s1!=i)&&min2>HT[i].weight)
    {
      *s2=i;
      min2=HT[i].weight;
    }
  }
}

Huffman HuffmanCoding(Huffman Hfm)
{
  /*---------------------------------*/
  int i,n,m,s1,s2,start;
  int c,f;
  char *cd;
  n=Hfm.longth;
  if(n<=1)  return Hfm;
  m=2*n-1;
 
  for(i=n+1;i<=m;++i)
  {
    Select(Hfm.HT,i-1,&s1,&s2);
    Hfm.HT[s1].parent=i;
    Hfm.HT[s2].parent=i;
    Hfm.HT[i].lchild=s1;
    Hfm.HT[i].rchild=s2;
    Hfm.HT[i].weight=Hfm.HT[s1].weight+Hfm.HT[s2].weight;
  }
  /*------------------------------------------*/
  Hfm.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=Hfm.HT[i].parent;f!=0;c=f,f=Hfm.HT[f].parent)
    {
      if(c==Hfm.HT[f].lchild)  cd[--start]='0';
      else cd[--start]='1';
    }
    Hfm.HC[i]=(char *)malloc((n-start)*sizeof(char));
    strcpy(Hfm.HC[i],&cd[start]);
  }
  free(cd);
  return Hfm;
}

Huffman InputHuffman(Huffman Hfm)
{
    int i,n;
    clrscr();
    printf("/n/n********************Initial*********************/n");
    printf("The chars and weights will be saved in the file /"hfmTree/"/n");
    printf("Please input the number of the chars: ");
    scanf("%d",&n);
    Hfm.HT=(HuffmanTree)malloc((2*n)*sizeof(HTNode));
    Hfm.c=(char *)malloc((n+1)*sizeof(char));
    for(i=1;i<=n;i++)
    {
      printf("Please input the char: ");
      scanf("%s",&Hfm.c[i]);
      printf("Please input the weight of the char: ");
      scanf("%d",&Hfm.HT[i].weight);
      Hfm.HT[i].parent=0;
      Hfm.HT[i].lchild=0;
      Hfm.HT[i].rchild=0;
    }
    for(;i<=2*n-1;++i)
    {
      Hfm.HT[i].weight=0;
      Hfm.HT[i].parent=0;
      Hfm.HT[i].lchild=0;
      Hfm.HT[i].rchild=0;
    }
    Hfm.longth=n;
    return Hfm;
}

Huffman InitHuffman(Huffman Hfm)
{
  int n,i;
  FILE *fp;
  fp=fopen("hfmTree","rt");
  if(fp==NULL)
  {
    Hfm=InputHuffman(Hfm);
    fp=fopen("hfmTree","wt");
    fprintf(fp,"%d/n",Hfm.longth);
    for(i=1;i<=Hfm.longth;i++)
      fprintf(fp,"%c %d",Hfm.c[i],Hfm.HT[i].weight);
    rewind(fp);
  }
  else
  {
    fscanf(fp,"%d/n",&n);
    Hfm.c=(char *)malloc((n+1)*sizeof(char));
    Hfm.HT=(HuffmanTree)malloc((2*n)*sizeof(HTNode));
    for(i=1;i<=n;i++)
      fscanf(fp,"%s %d",&Hfm.c[i],&Hfm.HT[i].weight);
    for(i=1;i<=n;i++)
    {
      Hfm.HT[i].parent=0;
      Hfm.HT[i].lchild=0;
      Hfm.HT[i].rchild=0;
    }
    for(;i<=2*n-1;++i)
    {
      Hfm.HT[i].weight=0;
      Hfm.HT[i].parent=0;
      Hfm.HT[i].lchild=0;
      Hfm.HT[i].rchild=0;
    }
    Hfm.longth=n;
  }
  fclose(fp);
  Hfm=HuffmanCoding(Hfm);
  return Hfm;
}


void Output(Huffman Hfm)
{
  int i,n;
  n=Hfm.longth;
  printf("/n/n******************Output the code of the chars****************/n/n");
  for(i=1;i<=n;i++)
  {
     printf("/n");
     printf("Char: %c/t",Hfm.c[i]);
     printf("Weight: %d/t",Hfm.HT[i].weight);
     printf("Code: ");
     puts(Hfm.HC[i]);
  }
}

void Encoding(Huffman Hfm)
{
  int i=0,j=0,n;
  char ch[MAX];
  FILE *fp,*ffp;
  n=Hfm.longth;
  printf("/n/n*******************Encoding**************************/n/n");
  if((ffp=fopen("ToBeTran","rt"))==NULL)
  {
    printf("/nPlease input the sentence: ");
    scanf("%s",&ch);
    printf("/n");
    fp=fopen("CodeFile","wt+");
  }
  else
  {
    fscanf(ffp,"%s",ch);
    fclose(ffp);
  }
  while(ch[j])
    {
      for(i=1;i<=n;i++)
    if(ch[j]==Hfm.c[i])
    {
      printf("%s",Hfm.HC[i]);
      fprintf(fp,"%s",Hfm.HC[i]);
      break;
    }
     j++;
   }
   rewind(fp);
   fclose(fp);
}

void Decoding(Huffman Hfm)
{
  HuffmanTree p;
  int i,n;
  int j=0;
  char d[50];
  FILE *fp;
  n=Hfm.longth;
  printf("/n/n******************Decoding************************/n/n");
  if((fp=fopen("CodeFile","rt"))==NULL)
  {
    printf("Please input the code:");
    scanf("%s",&d);
  }
  else
  {
    fscanf(fp,"%s",d);
    fclose(fp);
  }
  printf("/nThe file is : ");
  fp=fopen("TextFile","wt+");
  while(d[j])
  {
    p=&Hfm.HT[2*n-1];
    while(p->lchild||p->rchild)
    {
      if(d[j]=='0')
      { i=p->lchild;  p=&Hfm.HT[i]; }
      else
      { i=p->rchild;  p=&Hfm.HT[i]; }
      j++;
    }
    printf("%c",Hfm.c[i]);
    fprintf(fp,"%c",Hfm.c[i]);
  }
  fclose(fp);
}

Huffman RebuildHuffman(Huffman Hfm)
{
  int n,i;
  FILE *fp;
  fp=fopen("hfmTree","wt");
  Hfm=InputHuffman(Hfm);
  fprintf(fp,"%d/n",Hfm.longth);
  for(i=1;i<=Hfm.longth;i++)
  fprintf(fp,"%c %d",Hfm.c[i],Hfm.HT[i].weight);
  rewind(fp);
  fclose(fp);
  Hfm=HuffmanCoding(Hfm);
  return Hfm;
}

int main()
{
  Huffman Hfm;
  char choice='a';
  Hfm=InitHuffman(Hfm);
  while(choice!='q')
  {
    clrscr();
    printf("/n/n/n*************************************/n/n");
    printf("a. Encoding:/n/n");
    printf("b. Decoding:/n/n");
    printf("c. Print all codes:/n/n");
    printf("d. Rebuild the huffmantree:/n/n");
    printf("q. Quit.../n/n");
    printf("/n************************************/n/n");
    printf("Please enter your choice: ");
    scanf("%s",&choice);
    switch(choice)
    {
      case 'a':
       clrscr();
       Encoding(Hfm);
       printf("/n/n*******Please enter anykey to continue*******/n");
       getch(); break;
      case 'b':
       clrscr();
       Decoding(Hfm);
       printf("/n/n*******Please enter anykey to continue********/n");
       getch(); break;
      case 'c':
       clrscr();
       Output(Hfm);
       printf("/n/n*******Please enter anykey to continue********/n");
       getch(); break;
      case 'd':
       clrscr();
       Hfm=RebuildHuffman(Hfm);
       printf("/n/n********************Initial*********************/n");

       getch(); break;
      case 'q':
       break;
      default:
       printf(" Your choice is wrong!/n Please enter anykey to choice again!/n");
       getch(); break;
      }
    }
  return 0;
}

 

使用方法:

1.              选择a,输入句子,例如THIS-PROGRAM-IS-MY-FAVORITE,空格用“-”代替。

 

2.              选择b,程序将从CodeFile文件中读取代码,译为字符输出并保存到TextFile文件。

 

3.              选择c,输出赫夫曼树的所有字符,权值和赫夫曼代码。

 

4.              选择d,重建赫夫曼树。

 

5.              选择q,退出系统。

 

由于是在TC下弄的,所以没有注释,凑合着看吧,呵呵