哈夫曼编译码C语言实现

注:转载请标明出处本博客

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <malloc.h>
#define OK 1
#define ERROR 0
#define OVERFLOW -1
#define MAX_NUM 9999
#define MAX 60
typedef char **HuffmanCode;

typedef struct
{
      int    weight;//权重
      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)  //在HT[1]--HT[end]的范围内选择两个parents为零且权值最小的两个结点,序号值给s1,s2返回
{
   int i;
   int min1=MAX_NUM;//min1,min2标记最小的两个权值
   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;
   
     printf("\n\n\t\t*****************************************\n");
     printf("Please input the number of the chars: ");
     scanf("%d",&n);
     Hfm.HT=(HuffmanTree)malloc((2*n)*sizeof(HTNode));//Hfm.HT为指向HTNode的指针,对之初始化
     Hfm.c=(char *)malloc((n+1)*sizeof(char));
     for(i=1;i<=n;i++)
     {
       printf("请输入第%d个叶子字符: ",i);
       scanf("%s",&Hfm.c[i]);
       printf("请输入它的权重: ");
       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;
}
void Output(Huffman Hfm)//将所有的叶子的哈夫曼编码输出
{
   int i,n;
   n=Hfm.longth;
   printf("\n\n******************输出所有叶子的编码****************\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*******************报文编码**************************\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);
 printf("\n报文编码已成功!并已将结果保存到文件CodeFile\n");

}


void Decoding(Huffman Hfm)
{
   HuffmanTree p;
   int i,n;
   int j=0;
   char d[50];
   char c='a';
   FILE *fp;
   n=Hfm.longth;
   printf("\n\n******************译码************************\n\n");
   while(c!='o')
   {
   printf("\t\ta,从文件'CodeFile'中读取\n\n");
   printf("\t\tb,重新输入编码文件\n\n");
   printf("\t\to,退出\n\n");
   printf("\t\t请选择");
   scanf("%s",&c);
   switch(c)
   {
   case 'a':
  
     if((fp=fopen("CodeFile","rt"))==NULL)
   printf("文件CodeFile不存在,请先编码");
  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]);
    }
 break;

   case 'b':
   
    printf("请输入码文:");
       scanf("%s",&d);
       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]);
    }
 break;
  
   case 'o':break;
  
   }
   }
   fclose(fp);
   printf("\n译码已成功,并已将结果保存到文件'TextFile'中\n");
  
}

Huffman InitbuildHuffman(Huffman Hfm)
{
   int i;
   FILE *fp;
   fp=fopen("hfmTree","wt");
   Hfm=InputHuffman(Hfm);
   Hfm=HuffmanCoding(Hfm);
   fprintf(fp,"%d\n",Hfm.longth);
   for(i=1;i<=Hfm.longth;i++)
    fprintf(fp,"%c %d %s ",Hfm.c[i],Hfm.HT[i].weight,Hfm.HC[i]);
   rewind(fp);
   fclose(fp);
   printf("初始化已完毕,哈夫曼树创建成功并已保存到文件'HfmTree中'");
   return Hfm;
}
void PrintCoding(Huffman Hfm) //打印文件CodeFile中的内容
{
 int i=0;
 char *ch;
 ch=(char *)malloc(sizeof(char));
 FILE *fp,*fpp;
 fpp=fopen("CodeFile","rt");
 if(fpp==NULL)
 {printf("没有文件CodeFile,请先编码!\n");return;}
 else
 {
  fscanf(fpp,"%s",ch);
  fclose(fpp);
 }
 fp=fopen("CodePrin","wt+");
 printf("CodeFil文件内容为:");
 while(ch[i])
 {
  printf("%c",ch[i]);i++;
  if(i%50==0) printf("\n");
 }
 fprintf(fp,"%s",ch);
 fclose(fp);
 printf("已将文件CodeFile中的代码打印完毕\n,并将输出内容保存至文件CodePrin\n");
}
int main()
{ int v;
  printf("\t\t欢迎使用哈夫曼码的编/译码系统!\n\n");
  for(v=0;v<60;v++)
      printf("%c",3);
  printf("\t\t\t项目经理--翟周伟\n\n"); 
  printf("\t\t版权所有,盗版必究\n\n");  
  printf("\t\t在此系统中可以进行以下操作:"); 
  Huffman Hfm;
  char choice='a';
  while(choice!='f')
   {
      printf("\n\n\n\t\t*************************************\n\n");
      printf("\t\t\ta. 新建初始化哈夫曼树\n\n");
      printf("\t\t\tb. 对报文进行哈夫曼树编码\n\n");
      printf("\t\t\tc. 报文译码\n\n");
      printf("\t\t\td. 输出所有编码\n\n");
      printf("\t\t\te. 打印代码文件\n\n");
      printf("\t\t\tf. 退出本哈夫曼码的编/译码系统\n\n");
      printf("\n\t\t************************************\n");
      printf("请选择: ");
      scanf("%c",&choice);
      switch(choice)
   {
    case 'a':
   
        Hfm=InitbuildHuffman(Hfm);
        printf("\n\n********************Initial*********************\n");

        getch(); break;
       case 'b':
   
        Encoding(Hfm);
        printf("\n\n*******Please enter anykey to continue*******\n");
        getch(); break;
       case 'c':
       
        Decoding(Hfm);
        printf("\n\n*******Please enter anykey to continue********\n");
        getch(); break;
       case 'd':
     
        Output(Hfm);
        printf("\n\n*******Please enter anykey to continue********\n");
        getch(); break;
        case 'e':
     
        PrintCoding(Hfm);
        printf("\n\n*******Please enter anykey to continue********\n");
        getch(); break;
      
       case 'f':
       
        printf("感谢你使用本系统,欢迎再次使用!\n");
  for(v=0;v<80;v++);
  printf("%c",3);
  getch();
  break;
       default:
        printf(" Your choice is wrong!\n Please enter anykey to choice again!\n");
        getch(); break;
       
       }
   }
    
   return 0;
}

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的C语言实现哈夫曼码的例子: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_TREE_HT 100 // 哈夫曼树结构体 struct HuffmanNode { char data; unsigned freq; struct HuffmanNode *left, *right; }; // 哈夫曼码结构体 struct HuffmanCode { char data; char *code; }; // 创建一个哈夫曼树节点 struct HuffmanNode* newNode(char data, unsigned freq) { struct HuffmanNode* node = (struct HuffmanNode*) malloc(sizeof(struct HuffmanNode)); node->left = node->right = NULL; node->data = data; node->freq = freq; return node; } // 建立一个哈夫曼树 struct HuffmanNode* buildHuffmanTree(char data[], int freq[], int size) { struct HuffmanNode *left, *right, *top; int i; // 创建一个最小堆,用于存放节点 struct MinHeap* minHeap = createMinHeap(size); // 将所有节点插入到最小堆中 for (i = 0; i < size; ++i) { insertMinHeap(minHeap, newNode(data[i], freq[i])); } // 循环直到最小堆只剩下一个节点 while (!isSizeOne(minHeap)) { // 取出最小的两个节点 left = extractMin(minHeap); right = extractMin(minHeap); // 创建一个新节点作为它们的父节点 // 每次都将最小的两个节点合并成一个新的节点,并将其频率设置为这两个节点的频率之和 top = newNode('$', left->freq + right->freq); top->left = left; top->right = right; // 将新节点插入到最小堆中 insertMinHeap(minHeap, top); } // 最后剩下的节点就是根节点,也就是整个哈夫曼树 return extractMin(minHeap); } // 将哈夫曼码存储到数组中 void encode(struct HuffmanNode* root, char* code, int top, struct HuffmanCode huffmanCode[]) { if (root->left) { code[top] = '0'; encode(root->left, code, top + 1, huffmanCode); } if (root->right) { code[top] = '1'; encode(root->right, code, top + 1, huffmanCode); } // 如果是叶子节点,则将其码存储到哈夫曼码结构体中 if (!root->left && !root->right) { huffmanCode[root->data].data = root->data; huffmanCode[root->data].code = (char*) malloc(sizeof(char) * (top + 1)); strcpy(huffmanCode[root->data].code, code); } } // 打印哈夫曼码 void printHuffmanCodes(struct HuffmanCode huffmanCode[], int size) { printf("Huffman Codes:\n"); for (int i = 0; i < size; ++i) { if (huffmanCode[i].code) { printf("%c - %s\n", huffmanCode[i].data, huffmanCode[i].code); } } } // 哈夫曼码主函数 void HuffmanCodes(char data[], int freq[], int size) { struct HuffmanNode* root = buildHuffmanTree(data, freq, size); // 创建一个哈夫曼码结构体数组,用于存储每个字符的哈夫曼码 struct HuffmanCode huffmanCode[size]; char code[MAX_TREE_HT]; int top = 0; encode(root, code, top, huffmanCode); printHuffmanCodes(huffmanCode, size); } int main() { char data[] = {'a', 'b', 'c', 'd', 'e', 'f'}; int freq[] = {5, 9, 12, 13, 16, 45}; int size = sizeof(data) / sizeof(data[0]); HuffmanCodes(data, freq, size); return 0; } ``` 以上代码实现了一个简单的哈夫曼码,它会将给定的字符数组和频率数组作为输入,并输出每个字符的哈夫曼码。当然,这只是一个基础的实现,实际上哈夫曼码还有很多优化和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值