哈弗曼编码 译码器.docx
- 文档编号:3794811
- 上传时间:2022-11-25
- 格式:DOCX
- 页数:14
- 大小:18.77KB
哈弗曼编码 译码器.docx
《哈弗曼编码 译码器.docx》由会员分享,可在线阅读,更多相关《哈弗曼编码 译码器.docx(14页珍藏版)》请在冰豆网上搜索。
哈弗曼编码译码器
系统应具备以下功能:
1,构造哈夫曼数及哈夫曼编码:
从终端读入字符集大小为n,n个字符窜以及n个对应的权值,建立哈夫曼树;利用以建好的哈夫曼树求每个叶子节点的哈夫曼编码,并保存。
2,编码:
利用以建好的哈夫曼编码对明文文件中的正文进行编码,然后将结果存入密文文件中。
3,译码:
将密文中的0、1代码序列进行译码。
4,打印密文文件:
将文件以紧凑的格式显示在终端显示器上,没三十行一个代码;同时,将此字符形式的编码文件保存。
5,打印哈夫曼树及哈夫曼编码:
将已在内存中的哈夫曼树以凹入表示形式显示在终端显示器上,同是将每个字符的哈夫曼编码显示出来,并保存到文件
注释非常详细,希望对你有所帮助!
#ifndefHuffman_Tree_h
#defineHuffman_Tree_h
#endif
#include
typedefstruct{
unsignedintweight;
unsignedintparent,lchild,rchild;
}HTNode,*HuffmanTree;//存储赫夫曼树的结点类型
typedefchar**HuffmanCode;//用于存储字符集中各个字符相应的赫夫曼编码
voidstrcpy(char*S1,char*S2){//将字符串S2复制到S1
inti=0;
while(S2[i]!
='\0'){
S1[i]=S2[i];
i++;
}
S1[i]='\0';
}
voidSelect(HuffmanTreeHT,intt,int&s1,int&s2){//在HT[1]到HT[t-1]中找出权值最小的两个S1和S2
inti=1;
s1=s2=0;
HT[0].weight=65535;
while(i<=t){//遍历查找权值最小的结点S1
if(HT[i].parent==0&&HT[i].weight s1=i; i++; } i=1; while(i<=t){//遍历查找除S1外权值最小的结点S2 if(i! =s1&&HT[i].parent==0&&HT[i].weight s2=i; i++; } } intHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,int*w,intn){//根据各个字符的权值构造赫夫曼树HT,将对应的赫夫曼编码存储在HC中 ints1,s2,m,i,start; unsignedintc,f; HTNode*p; char*cd; if(n<=1)return0; m=2*n-1;//赫夫曼树的总结点树为m HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));//申请存储赫夫曼树的空间 for(p=HT+1,i=1;i<=n;++i,++p,++w){//将各个叶子结点的weight赋以相应的权值,parent,lchild,rchild均赋为0 p->weight=*(w+1); p->parent=p->lchild=p->rchild=0; } for(;i<=m;++i,++p){//将各个非叶子结点的weight,parent,lchild,rchild均赋为0 p->weight=p->parent=p->lchild=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;//编码在数组cd[]中的最前位置 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]=(char*)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间 strcpy(HC[i],&cd[start]);//将cd[]数组的start位置到n-1位置复制给HC[i] } free(cd);//释放空间 return1; } 以上为第一部分 #include #include #include"Huffman_Tree.h" #defineYes1//当程序已经调用过初始化赫夫曼树的InitHuff_T()函数,或已从htfTree文件读取过,则将Init_Mode置为Yes,否则为No #defineNo0 voidInitHuff_T(HuffmanTree&HT,HuffmanCode&HC,charch[],int&n){//初始化赫夫曼数,要求用户输入字符和相应权值 inti=1,w[100],tem,j; chara[20]; FILE*save; printf("请输入编码字符集的大小n: "); scanf("%d",&n);//获取用户输入的字符集个数 while(i<=n){//获取用户输入的字符和相应权值,分别存储在ch[]和w[]数组中 printf("请输入第%d个字符和该字符的权值w: ",i); fflush(stdin); scanf("%c%d",&ch[i],&w[i]); i++; } ch[i]='\0'; HuffmanCoding(HT,HC,w,n);//根据用户的输入,生成赫夫曼数及各个字符相应的赫夫曼编码,分别存在HT树和HC中 if((save=fopen("htfTree","w"))==NULL){//打开用于存储赫夫曼树的文件 printf("Openfilefail......\n"); exit(0); } tem=n;//接下来的14行是将字符集大小转换成字符形式写入到文件中 j=0; while(tem! =0){ tem=tem/10; j++; } tem=n; a[j]='\0'; while(tem! =0){ a[j-1]=(char)(tem%10+48); tem=tem/10; j--; } fputs(a,save); printf("%d\n",n);//向屏幕输出字符集大小n fputc('\n',save); for(i=1;i<=n;i++){//分别向文件和屏幕输出各个字符和相应的赫夫曼编码 fputc(ch[i],save);printf("%c\t",ch[i]); fputc('\t',save); fputs(HC[i],save);printf("%s\n",HC[i]); fputc('\n',save); } for(i=1;i<=2*n-1;i++){//将赫夫曼树各个结点的parent,lchild,rchild分别写入到文件中 tem=HT[i].parent;//将i结点的parent转换成字符并写入到文件中 if(tem==0){ fputc(tem+48,save); fputc('',save); } else{ j=0; while(tem! =0){ tem=tem/10; j++; } tem=HT[i].parent; a[j]='\0'; while(tem! =0){ a[j-1]=(char)(tem%10+48); tem=tem/10; j--; } fputs(a,save); fputc('',save); } tem=HT[i].lchild;//将i结点的lchild转换成字符并写入到文件中 if(tem==0){ fputc(tem+48,save); fputc('',save); } else{ j=0; while(tem! =0){ tem=tem/10; j++; } tem=HT[i].lchild; a[j]='\0'; while(tem! =0){ a[j-1]=(char)(tem%10+48); tem=tem/10; j--; } fputs(a,save); fputc('',save); } tem=HT[i].rchild;//将i结点的rchild转换成字符并写入到文件中 if(tem==0){ fputc(tem+48,save); fputc('\n',save); } else{ j=0; while(tem! =0){ tem=tem/10; j++; } tem=HT[i].rchild; a[j]='\0'; while(tem! =0){ a[j-1]=(char)(tem%10+48); tem=tem/10; j--; } fputs(a,save); fputc('\n',save); } } fclose(save); } voidEncoding(HuffmanTree&HT,HuffmanCode&HC,charch[]){//根据赫夫曼编码将用户指定的文件中的字符编成相应的编码,并将所得编码存储到用户指定文件 FILE*ToBeTran,*CodeFile; charToBeTran_Name[100],CodeFile_Name[100];//存储用户指定文件的文件名 inti; charc; printf("请输入所要进行编码的文件的文件名: "); scanf("%s",ToBeTran_Name);//获得所要进行编码的文件的文件名 if((ToBeTran=fopen(ToBeTran_Name,"r"))==NULL){//打开文件 printf("Openfilefail......\n"); exit(0); } printf("请输入编码后编码表示的信息所存储到的文件的文件名: "); scanf("%s",CodeFile_Name);//获得编码后编码表示的信息所存储到的文件的文件名 if((CodeFile=fopen(CodeFile_Name,"w"))==NULL){//打开文件 printf("Openfilefail......\n"); exit(0); } c=fgetc(ToBeTran);//从文件读取一个字符 while(c! =EOF){//对文件中的各个字符进行编码,直至文件结尾 i=1; while(c! =ch[i]&&ch[i]! ='\0')//在ch[]数组中查找从文件读取的字符 i++; if(ch[i]=='\0'){//未找到,c不在ch[]数组中,c无法被识别,程序出错,退出 printf("字符%c无法识别,程序将退出。 \n",c); exit(0); } fputs(HC[i],CodeFile);//若找到,则将c相应的赫夫曼编码写入到文件中 printf("%s",HC[i]);//将c相应的赫夫曼编码输出到屏幕 c=fgetc(ToBeTran);//读入文件中的下一个字符 } printf("\n"); fclose(ToBeTran); fclose(CodeFile); } voidDecoding(HuffmanTreeHT,charch[],intn){//对指定的存储由赫夫曼编码表示的信息的文件进行译码,翻译成相应的字符表示,并存储到指定文件 intp,i=1; charcode[1000],c; charCodeFile_Name[100],TextFile_Name[100];//存储用户指定文件的文件名 p=2*n-1; FILE*CodeFile,*TextFile; printf("请输入所要译的文件名: "); scanf("%s",CodeFile_Name);//获得所要译的文件的文件名 if((CodeFile=fopen("CodeFile","r"))==NULL){//打开文件 printf("Openfilefail......\n"); exit(0); } printf("请输入译后的字符存储到的文件的文件名: "); scanf("%s",TextFile_Name);//获得译后的字符存储到的文件的文件名 if((TextFile=fopen(TextFile_Name,"w"))==NULL){//打开文件 printf("Openfilefail......\n"); exit(0); } c=fgetc(CodeFile); while(c! =EOF){ code[i]=c; i++; c=fgetc(CodeFile); } code[i]='\0';//从文件读取字符,存储在code[]数组中 i=1; while(code[i]! ='\0'&&p! =0){//对数组code[]中的赫夫曼编码进行译码 if(code[i]=='0') p=HT[p].lchild;//进入左分支 else p=HT[p].rchild;//进入右分支 if(! HT[p].lchild&&! HT[p].rchild){//进入叶子结点 fputc(ch[p],TextFile);//将相应的字符写入到文件中 printf("%c",ch[p]);//将相应的字符输出到屏幕 p=2*n-1;//重新从树根出发进行译码 } i++; } printf("\n"); } voidReadHuff_T(HuffmanTree&HT,HuffmanCode&HC,charch[],int&n){//从文件读取赫夫曼树 FILE*htfTree; charc[100],ch1; inti,j,t; if((htfTree=fopen("htfTree","r"))==NULL){//打开存有赫夫曼树信息的文件 printf("Openfilefail......\n"); exit(0); } fgets(c,10,htfTree);//获取赫夫曼树叶子结点个数的字符串表示形式 i=0;//以下6行将字符串形式转换成整数形式 while(c[i]! ='\n') i++; n=0; for(j=0;j n=10*n+c[j]-'0';//求出叶子结点数n HC=(HuffmanCode)malloc((n+1)*sizeof(char*));//申请HC空间 HT=(HuffmanTree)malloc((2*n)*sizeof(HTNode));//申请赫夫曼树存储空间 i=1; while(i<=n){ ch[i]=fgetc(htfTree);//读取字符集中的一个字符 HC[i]=(char*)malloc((10)*sizeof(char));//申请用于存储读取到的字符集中的字符的赫夫曼编码的空间 fgetc(htfTree);//将‘\t’输出 ch1=fgetc(htfTree);//读取赫夫曼编码,存储在相应的HC[i][]数组里 intj=0; while(ch1! ='\n'){ HC[i][j]=ch1; j++; ch1=fgetc(htfTree); } HC[i][j]='\0'; i++; } ch[i]='\0'; i=0; while(i<2*n-1){//读取赫夫曼树的各个结点的parent,lchild,rchild.并赋值到赫夫曼树HT中 ch1=fgetc(htfTree);//读取parent的字符串形式,存储在c[]中,并将其转换成整数形式,赋给HT[i].parent j=0; while(ch1! =''){ c[j]=ch1; j++; ch1=fgetc(htfTree); } HT[i+1].parent=0; for(t=0;t HT[i+1].parent=10*HT[i+1].parent+c[t]-'0'; ch1=fgetc(htfTree);//读取lchild的字符串形式,并将其转换成整数形式,赋给HT[i].lchild j=0; while(ch1! =''){ c[j]=ch1; j++; ch1=fgetc(htfTree); } HT[i+1].lchild=0; for(t=0;t HT[i+1].lchild=10*HT[i+1].lchild+c[t]-'0'; ch1=fgetc(htfTree);//读取rchild的字符串形式,并将其转换成整数形式,赋给HT[i].rchild j=0; while(ch1! ='\n'){ c[j]=ch1; j++; ch1=fgetc(htfTree); } HT[i+1].rchild=0; for(t=0;t HT[i+1].rchild=10*HT[i+1].rchild+c[t]-'0'; i++; } } intmain(){ HuffmanTreeHT; HuffmanCodeHC; charch[100];//用于存储字符集 intn,Init_Mode=No;//n为字符集的大小,Init_Mode=No表示内存中没有赫夫曼树的信息 charmode;//让用户选择不同的操作 printf("请输入你要选择的功能\n"); printf("\t\tI--初始化\t\tE--编码\n"); printf("\t\tD--译码\t\tQ--退出程序\n"); scanf("%c",&mode);//获得用户选择的操作 while(mode! ='Q'&&mode! ='q'){//当用户输入不为Q或q时,执行相应操作 switch(mode){ case'I': InitHuff_T(HT,HC,ch,n); Init_Mode=Yes; break; case'i': InitHuff_T(HT,HC,ch,n); Init_Mode=Yes; break; case'E': if(No==Init_Mode) ReadHuff_T(HT,HC,ch,n); Encoding(HT,HC,ch); Init_Mode=Yes; break; case'e': if(No==Init_Mode) ReadHuff_T(HT,HC,ch,n); Encoding(HT,HC,ch); Init_Mode=Yes; break; case'D': if(No==Init_Mode) ReadHuff_T(HT,HC,ch,n); Decoding(HT,ch,n); Init_Mode=Yes; break; case'd': if(No==Init_Mode) ReadHuff_T(HT,HC,ch,n); Decoding(HT,ch,n); Init_Mode=Yes; default: printf("您的输入有错,请重新选择.\n"); } printf("请输入你要选择的功能\n"); printf("\tI--初始化\tE--编码\n"); printf("\tD--译码\tQ--退出程序\n"); fflush(stdin); scanf("%c",&mode);//让用户继续选择相应的操作,直至用户选择退出 } return0; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 哈弗曼编码 译码器 哈弗曼 编码