哈弗曼编码 译码器.docx

上传人:b****5 文档编号:3794811 上传时间:2022-11-25 格式:DOCX 页数:14 大小:18.77KB
下载 相关 举报
哈弗曼编码 译码器.docx_第1页
第1页 / 共14页
哈弗曼编码 译码器.docx_第2页
第2页 / 共14页
哈弗曼编码 译码器.docx_第3页
第3页 / 共14页
哈弗曼编码 译码器.docx_第4页
第4页 / 共14页
哈弗曼编码 译码器.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

哈弗曼编码 译码器.docx

《哈弗曼编码 译码器.docx》由会员分享,可在线阅读,更多相关《哈弗曼编码 译码器.docx(14页珍藏版)》请在冰豆网上搜索。

哈弗曼编码 译码器.docx

哈弗曼编码译码器

系统应具备以下功能:

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;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 语文

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1