哈夫曼树编码译码

匿名 (未验证) 提交于 2019-12-03 00:09:02

一:问题描述

【问题描述】
利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编/译码系统。
【任务要求】
一个完整的系统应具有以下功能:
1) I:初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
2) E:编码(Encoding)。利用已建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
3) D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。

【测试数据】
用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”。

字符   A B C D E F G H I J K L M
频度 186 64 13 22 32 103 21 15 47 57 1 5 32 20
字符 N O P Q R S T U V W X Y Z  
频度 57 63 15 1 48 51 80 23 8 18 1 16 1  

 

 

 

 

 

二:大致思路

1.构建哈夫曼树

有n个字母待建树,申请p[2n-1]个结构体数组空间,将各个字母及其权值存入结构体数组,将数组按照权值进行排序,每次选取最小的两个构建哈夫曼树,每次从上次选择的下一个开始选择,即第一次p[0],p[1]则第二次p[2],p[3],以此类推,每次生成的从p[n+1]开始存入,直至数组就剩下一个元素,即为根节点。

2.编码

从叶子结点(带权字母即叶子结点,从1步骤的结构体数组那里入手,需要判断一下是否为叶子结点)开始向上回溯即寻找父节点,若为父节点左子树编码为‘0’字符,反之为‘1’字符,建个数组从最后一位往前存入直至父节点为空即根节点,直至结构体数组最后一个元素。然后将存储的字母的编码和待编码的字符串进行比对,将字符串译码为01结构,编码完成。

3.译码

将01结构的编码从根节点开始译码,0往左子树遍历1往右子树,直至叶节点,译码出一个字母,然后再从根节点开始,循环操作直至所有都译码完成。

三:具体实现

#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; typedef struct node {     char ch[2];     int weight;     char ldata,rdata;     node *lchild,*rchild,*parent; }*huffman; typedef struct encoding {     char ch[2];     char *data; }*encode1; void paixu(huffman *p,int m) {     huffman temp;     for(int i=0;i<m-1;i++)     {         for(int j=i+1;j<m;j++)         {             if(p[i]->weight>p[j]->weight)             {                 temp=p[i];                 p[i]=p[j];                 p[j]=temp;             }         }     } } huffman* Read(int n)                                                  //读取英文字母 {     huffman *huff;     FILE *fp;     huff=new huffman[2*n-1];     for(int i=0;i<2*n-1;i++)     {         huff[i]=new node;         huff[i]->lchild=huff[i]->rchild=NULL;     }     if((fp=fopen("hfmTree.txt","w"))==NULL)     {cout<<"文件打开失败!";exit(0);}     cout<<"please input the letter:"<<endl;     for(int i=0;i<n;i++)     {         huff[i]->ch[0]=cin.get();         if(huff[i]->ch[0]=='\n')         huff[i]->ch[0]=cin.get();         cin>>huff[i]->weight;         cin.get();         huff[i]->ch[1]='\0';         fprintf(fp,"%s%d ",huff[i]->ch,huff[i]->weight);     }     cout<<"hfmTree.txt文件写入完成!"<<endl;     fclose(fp);     return huff; } node* Crhuffman(huffman* p,int n,int *n1)                             //创建哈夫曼树 {     int m=n;     for(int i=0;i<2*n-1;i+=2)     {         if((m-1)!=i)         {             paixu(p,m);             p[m]->weight=p[i]->weight+p[i+1]->weight;             p[m]->lchild=p[i];             p[m]->rchild=p[i+1];             p[i]->parent=p[m];             p[i+1]->parent=p[m];             m+=1;         }         else         {p[m-1]->parent=NULL;break;}     }     *n1=m;     return p[m-1]; } int Code(huffman *p,int n,int t,char *c,int c1,char *c2)                     //哈弗曼编码 {     huffman q;     FILE *fp;     q=new node;     int k=0,k1=t-1,kk=0;     encode1 *encode;     encode=new encode1[t];     for(int i=0;i<t;i++)     {         encode[i]=new encoding;         encode[i]->data=new char[t];     }     for(int i=0;i<t;i++)     {         for(int j=0;j<t;j++)         {             encode[i]->data[j]='a';         }     }     for(int i=0;i<n;i++)     {         if(p[i]->lchild==NULL&&p[i]->rchild==NULL)         {             q=p[i];             encode[k]->ch[0]=p[i]->ch[0];             while(q->parent!=NULL)             {                 if(q->parent->lchild==q)                 encode[k]->data[k1]='0';                 else                 encode[k]->data[k1]='1';                 q=q->parent;                 k1=k1-1;             }             k+=1;             k1=t-1;         }     }     if((fp=fopen("CodeFile.txt","w"))==NULL)     {cout<<"文件打开失败!"<<endl;exit(0);}     for(int i=0;i<t;i++)     {         encode[i]->ch[1]='\0';         fprintf(fp,"%s:",encode[i]->ch);         for(int j=0;j<t;j++)         {             if(encode[i]->data[j]!='a')             {                fprintf(fp,"%c",encode[i]->data[j]);                if(j==t-1)                fprintf(fp,"\n");             }         }     }     for(int i=0;i<c1;i++)//编码     {         for(int j=0;j<t;j++)         {             if(c[i]==encode[j]->ch[0])             for(int k2=0;k2<t;k2++)             {                 if(encode[j]->data[k2]!='a')                 {                   c2[kk]=encode[j]->data[k2];                   kk+=1;                 }             }         }     }     c2[kk]='\0';     fprintf(fp,"#题目所给英文编码: %s",c2);     cout<<"CodeFile文件写入完成!"<<endl;     fclose(fp);     return kk; } int Readtxt(char *c)                                            //读取英文字符串 {     int m=0;     FILE *fp;     cout<<"请输入需要编码的大写英文:"<<endl;     if((fp=fopen("ToBeTran.txt","w"))==NULL)     {cout<<"文件打开失败!";exit(0);}     for(int i=0;;i++)     {             c[i]=cin.get();             if(c[i]=='\n')             {c[i]='\0';break;}             m+=1;     }     fprintf(fp,"%s",c);     fclose(fp);     cout<<"ToBeTran.txt文件写入完成!"<<endl;     return m; } void Initialization(huffman **p,node **p1,int &n,int &n1)             //初始化 {     cout<<"请输入待插入英文字母个数:"<<endl;     cin>>n;     *p=Read(n);     *p1=Crhuffman(*p,n,&n1); } void Encoding(int &c1,char **c,char **c2,int n,int n1,huffman *p)    //编码 {     c1=Readtxt(*c);     Code(p,n1,n,*c,c1,*c2); } void Decoding(node *p1,char *c)                                      //译码 {     int k=0,i=0;     FILE *fp;     node *p=p1;     if((fp=fopen("TextFile.txt","w"))==NULL)     {cout<<"文件打开失败!";exit(0);}     while(c[i]!='\0')     {         while(c[i]!='\0')         {             if(c[i]=='0')             {                 p=p->lchild;                 if(p->lchild==NULL&&p->rchild==NULL)                 {i++;break;}             }             else             {                 p=p->rchild;                 if(p->lchild==NULL&&p->rchild==NULL)                 {i++;break;}             }             i++;         }         fprintf(fp,"%s",p->ch);p=p1;     }     fclose(fp);cout<<"TextFile.txt文件写入完成!"<<endl; } void Print()                                                //打印 {     FILE *fp,*fp1;     char ch[1000];     if((fp=fopen("CodeFile.txt","r"))==NULL)     {cout<<"文件打开失败!"<<endl;exit(0);}     if((fp1=fopen("CodePrint.txt","w"))==NULL)     {cout<<"文件打开失败!"<<endl;exit(0);}     while(!feof(fp))     {         fscanf(fp,"%s",ch);         if(ch[0]=='#')         {             cout<<ch<<endl;             fscanf(fp,"%s",ch);             fprintf(fp1,"%s",ch);         }         cout<<ch<<endl;     }     fclose(fp);     fclose(fp1); } void Tree_printing(node *p1) {     FILE *fp;     if((fp=fopen("TreePrint.txt","a"))==NULL)     {cout<<"文件打开失败!"<<endl;exit(0);}     if(p1)     {         if(p1->ch[0]==NULL)         {             cout<<"空"<<p1->weight<<"    ";             fprintf(fp,"空%d\n",p1->weight);         }          else         {             cout<<p1->ch[0]<<p1->weight<<"     ";             fprintf(fp,"%c%d\n",p1->ch[0],p1->weight);         }          Tree_printing(p1->lchild);         Tree_printing(p1->rchild);     } } void homepage() {     cout<<"****************************************************************************"<<endl;     cout<<"               1.Initialization()&&Encoding()    //初始化并编码             "<<endl;     cout<<"               2.Decoding()                      //译码                     "<<endl;     cout<<"               3.Print()                         //打印代码文件             "<<endl;     cout<<"               4.Tree_printing()                 //打印哈夫曼树             "<<endl;     cout<<"               5.Confirm exit                    //确认退出                 "<<endl;     cout<<"****************************************************************************"<<endl;     cout<<"请选择需要的操作:"<<endl; } void display() {     int N;huffman *p,i=0;     node *p1;     encode1 *q;     char *c,*c2;     c=new char[100];     c2=new char[1000];     int n,n1,c1,n2;     homepage();     cin>>N;     while(1)     {           system("cls");           if(N==1)           {               Initialization(&p,&p1,n,n1);               Encoding(c1,&c,&c2,n,n1,p);               i+=1;           }           else if(N==2)           {               if(i==0)               {cout<<"操作不合法,请重新输入!"<<endl;}               else               {Decoding(p1,c2);i+=1;}           }           else if(N==3)           {               if(i==0)               {cout<<"操作不合法,请重新输入!"<<endl;}               else               {cout<<"PP";Print();i+=1;}           }           else if(N==4)           {             if(i==0)             {cout<<"操作不合法,请重新输入!"<<endl;}             else             {Tree_printing(p1);i+=1;cout<<endl;}           }           else if(N==5)           exit(0);           else           printf("输入不合法,请重新输入!\n");
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!