在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例C/C++语言基础 → 哈夫曼编/译码器(beta3.c)

哈夫曼编/译码器(beta3.c)

C/C++语言基础

下载此实例
  • 开发语言:C/C++
  • 实例大小:8.23KB
  • 下载次数:16
  • 浏览次数:140
  • 发布时间:2020-05-19
  • 实例类别:C/C++语言基础
  • 发 布 人:wzs200307
  • 文件格式:.c
  • 所需积分:0
 相关标签: c 数据结构 哈夫曼树

实例介绍

【实例简介】


发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码。

1)接收原始数据: 从终端读入字符集大小nn个字符和n个权值,建立哈夫曼树,存于文件hfmtree.dat中。

2)编码: 利用已建好的哈夫曼树(如不在内存,则从文件hfmtree.dat中读入)对文件中的正文进行编码,然后将结果存入文件codefile.dat中。

3)译码: 利用已建好的哈夫曼树将文件codefile.dat中的代码进行译码,结果存入文件textfile.dat 中。

4)打印编码规则即字符与编码的一一对应关系。

5)打印哈夫曼树将已在内存中的哈夫曼树以直观的方式显示在终端上。



【实例截图】

from clipboard

【核心代码】

#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
int j=0;

typedef int Status;
typedef char **HuffmanCode;

typedef struct{
     unsigned int    weight;//字符对应的权值 
     unsigned int    parent,lchild,rchild;
}HTNode,*HuffmanTree;//此处定义了哈夫曼树节点的数据类型。提供给Huffman使用

typedef struct{
     HuffmanTree HT;
     char         *c;//存放将要建立哈夫曼树的字符
     int          longth;//字符的大小,即开始第一步输入的一个整数
     HuffmanCode HC;//存放对应的哈夫编码即对应的01代码
}Huffman;

void Select(HuffmanTree HT,int end,int *s1,int *s2)
//把输入的字符按权值从小到大排序,挑出最小权值供HuffmanCoding()调用
//并且根节点的权值等于他的左右孩子的权值和
//min2是在剩下的字符中挑出的最小的劝值的字符

{
   int i;
   int min1=MAX_NUM;//min1是根节点的权值
   int min2;//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;
     }
   }
   //test printf("qqqqq%d\nWWWWW%d\n",min1,min2);
}

Huffman HuffmanCoding(Huffman Hfm)//将输入的字符以及他的权值,按照哈夫曼规则建立2叉树
{
   /*---------------------------------*/
   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;
//构造哈夫曼树时候,根节点的权值等于他的左右孩子权值和

//test printf("ht%d\ns1--%d\ns2--%d", Hfm.HT[i].weight,s1,s2);
   }
   /*------------------------------------------*/
   Hfm.HC=(HuffmanCode)malloc((n 1)*sizeof(char *));
   cd=(char *)malloc(n*sizeof(char));
   cd[n-1]='\0';
   //中间变量用来存储字符对应的哈夫曼01编码
   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]);
//将cd[]的值存储到变量Hfm.HC[i]中
//该变量在Huffman数据类型中有定义
   }
   free(cd);
   return Hfm;
}

Huffman InputHuffman(Huffman Hfm)//接收原始数据: 从终端读入字符集大小n,n个字符和n个权值,
//建立哈夫曼树,存于文件hfmtree.dat中。供InitHuffman()函数调用
{
     int i,n;
     printf("\n\n\t\t********************构造哈夫曼树*********************\n");
     printf("\t字符以及它的权值,数据将保存到同名目录下的'hfmTree.dat'\n");
     printf("请输入字符的个数: ");
     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 )//接收数据,并初始话,左右孩子节点赋0
     {
       printf("请输入字符\n: ");
       scanf("%s",&Hfm.c[i]);
       printf("请输入他的权值\n: ");
       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)//初始化哈夫曼树,调用InputHuffman(),HuffmanCoding()函数
//将数据存入文件,如果文件以存在,那么直接读取数据,进行哈夫编码
{
   int n,i;
   FILE *fp;
   fp=fopen("hfmTree.dat","rt");
   if(fp==NULL)
   {
     Hfm=InputHuffman(Hfm);
     fp=fopen("hfmTree.dat","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******************它的编码规则****************\n\n");
   for(i=1;i<=n;i )
   {
      printf("\n");
      printf("字符: %c\t",Hfm.c[i]);
      printf("权值: %d\t",Hfm.HT[i].weight);
      printf("对应的哈夫曼编码: ");
      puts(Hfm.HC[i]);
   }
    printf("\n\n******************打印哈夫曼树****************\n\n");
   for(i=n;i>=1;i--)
   {   if(n==i)
   {       printf("\t\t*\n\n");
           printf("\t%c\t\t*\n\n",Hfm.c[i]);
   }
   else if(i!=2&&i!=1)
   {
   for(j=0;j<=n-i;j )
   printf("\t");
   printf("%c\t\t*\n\n",Hfm.c[i]);
   }
   else if(i==2)
   { for(j=0;j<=n-i;j )
   printf("\t");
printf("%c\t\t%c\n\n",Hfm.c[i],Hfm.c[1]);
   }
   else if(i==1)
    printf("\n\n");
}
 
}

void Encoding(Huffman Hfm)
//编码: 利用已建好的哈夫曼树(如不在内存,则从文件hfmtree.dat中读入)
//对文件中的正文进行编码,然后将结果存入文件codefile.dat中。
//如果正文中没有要编码的字符,则键盘读入并存储到ToBeTran文件中
//读入ToBeTran中将要编码的内容,将编码好的哈夫曼编码存储到CodeFile中
{
   int i=0,j=0,n;
   char ch[MAX];
   FILE *fp,*ffp;
   n=Hfm.longth;
   printf("\n\n*******************编码**************************\n\n");
   if((ffp=fopen("ToBeTran.dat","rt"))==NULL)
   {
     printf("\n请输入要进行编码的句子: ");
     scanf("%s",&ch);
     printf("\n");
     fp=fopen("CodeFile.dat","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)
//译码: 利用已建好的哈夫曼树将文件codefile.dat
//中的代码进行译码,结果存入文件textfile.dat 中
{
   HuffmanTree p;
   int i,n;
   int j=0;
   char d[50];
   FILE *fp;
   n=Hfm.longth;
   printf("\n\n******************译码************************\n\n");
   if((fp=fopen("CodeFile.dat","rt"))==NULL)
   {
     printf("输入哈夫曼码进行译码\n:");
     scanf("%s",&d);
   }
   else
   {
     fscanf(fp,"%s",d);
     fclose(fp);
   }
   printf("\nThe file is : ");
   fp=fopen("TextFile.dat","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);

}

int main()
{
   Huffman Hfm;
   char choice='a';
   Hfm=InitHuffman(Hfm);
   while(choice!='q')
   {
     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\tq. 退出...\n\n");
     printf("\n\t\t************************************\n\n");
     printf("请输入你的选择\n: ");
     scanf("%s",&choice);
     switch(choice)
     {
       case 'a':
        Encoding(Hfm);
        printf("\n\n*******Please enter anykey to continue*******\n");
        getch(); break;
       case 'b':
        Decoding(Hfm);
        printf("\n\n*******Please enter anykey to continue********\n");
        getch(); break;
       case 'c':
        Output(Hfm);
        printf("\n\n*******Please enter anykey to continue********\n");
        getch(); break;
        case 'q':
        break;
       default:
        printf(" 选择错误!\n Please enter anykey to choice again!\n");
        getch(); break;
       }
     }
   return 0;
}
 

 

实例下载地址

哈夫曼编/译码器(beta3.c)

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警