哈夫曼编码译码器系统.docx
《哈夫曼编码译码器系统.docx》由会员分享,可在线阅读,更多相关《哈夫曼编码译码器系统.docx(25页珍藏版)》请在冰豆网上搜索。
哈夫曼编码译码器系统
1、系统开发的背景.......................................................................................................
(1)
2、系统分析与设计.......................................................................................................
(1)
3、系统的设计与实现...................................................................................................
(2)
(一)设计初始化(Initialization).......................................................................
(2)
(二)设计编码(Encoding).......................................................................................(3)
(三)设计译码(Decoding).......................................................................................(3)
(四)设计印代码文件(Print).................................................................................(4)
(五)设计印哈夫曼树(TreePrinting)...................................................................(4)
4、系统测试...................................................................................................................(5)
(一)测试main函数.....................................................................................................(5)
(二)测试编码(Encoding)及译码(Decoding)函数............................................(5)
(三)测试印代码文件(Print)函数..........................................................................(6)
(四)测试相关的根目录................................................................................................(6)
5、总结............................................................................................................................(6)
6、附件(代码、部分图表)........................................................................................(7)
哈夫曼编/译码器系统
一、系统开发的背景
为了提高信道利用率,缩短信息传输时间,降低传输成本,且在信息发送端通过一个编码系统对待传数据预先编码,在信息接收端将传来的数据进行译码(复原),因此设计哈夫曼编码/译码器系统。
二、系统分析与设计
(一)系统功能要求:
【任务要求】
I:
初始化(Initialization)。
从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。
E:
编码(Encoding)。
利用以建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。
D:
译码(Decoding)。
利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。
P:
印代码文件(Print)。
将文件CodeFile以紧凑格式显示在终端上,每行50个代码。
同时将此字符形式的编码文件写入文件CodePrin中。
T:
印哈夫曼树(TreePrinting)。
将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。
【测试数据】
利用教科书中的数据调试程序。
用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:
“THISPROGRAMISMYFAVORITE”。
字符
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所示。
图1哈夫曼编码/译码器系统功能图
通过上图的功能分析,把整个系统划分为5个模块:
1、初始化(Initialization),该模块主要实现:
初始化要编辑的语句,然后语句里面有个调用输入编码的语句len=InputCode();
2、编码(Encoding),该模块主要实现:
voidEncoding();
3、译码(Incoding),该模块主要实现:
voidDecoding();
4、印代码文件(Print),该模块主要实现:
由函数voidCode_printing()和函数voidCode_printing1()实现。
5、印哈夫曼树(TreePrinting),该模块主要实现:
coprint(p,HT);
三、系统的设计与实现
(一)初始化(Initialization),该模块主要实现
voidInitialization()
{inta,k,flag,len;
a=0;
len=InputCode();
for(i=0;i{k=0;flag=1;
cou[i-a].data=str[i];
cou[i-a].count=1;
while(i>k)
{
if(str[i]==str[k])
{
a++;flag=0;
}
k++;
if(flag==0)
break;
}
if(flag)
{
for(j=i+1;j{if(str[i]==str[j])
++cou[i-a].count;}
}
}
n=len-a;
for(i=0;i{
printf("%d%d",i,cou[i].data);
printf("%d%d\n",i,cou[i].count);
}
for(i=0;i<=n;i++)
{
*(z+i)=cou[i].data;
*(w+i)=cou[i].count;
}
(二)编码(Encoding),该模块主要实现
voidEncoding()
{
char*tran;
i=99;
tran=(char*)malloc(100*sizeof(char));
while(i==99)
{
if(fgets(tran,100,tobetran)==NULL)
{
printf("不能打开文件\n");
break;
}
for(i=0;*(tran+i)!
='\0';i++)
{
for(j=0;j<=n;j++)
{
if(*(z+j-1)==*(tran+i))
{
fputs(HC[j],codefile);
if(j>n)
{
printf("字符错误,无法编码!
\n");
break;
}
}
}
}
}
(三)译码(Decoding),该模块主要实现
voidDecoding()
{char*work,*work2,i2;
inti4=0,i,i3;
unsignedlonglength=10000;
work=(char*)malloc(length*sizeof(char));
fgets(work,length,codef);
work2=(char*)malloc(length*sizeof(char));
i3=2*n-1;
for(i=0;*(work+i-1)!
='\0';i++)
{
i2=*(work+i);
if(HT[i3].lchild==0)
{*(work2+i4)=*(z+i3-1);
i4++;
i3=2*n-1;
i--;
}
elseif(i2=='0')
i3=HT[i3].lchild;
elseif(i2=='1')
i3=HT[i3].rchild;
}
}
(四)印代码文件(Print),该模块主要实现
voidCode_printing1()
{char*work5;
work5=(char*)malloc(51*sizeof(char));
do
{
if(fgets(work5,51,txtfile)==NULL)
{
printf("不能读取文件\n");
break;
}
fputs(work5,CodePrin1);
puts(work5);
}while(strlen(work5)==50);
free(work5);
(五)印哈夫曼树(TreePrinting),该模块主要实现
voidTree_printing(HuffmanTreeHT,intw)
{
HuffmanTreep;
p=HT+w;
printf("下面打印哈夫曼树\n");
coprint(p,HT);
printf("打印工作结束\n");
}
四、系统测试
(一)测试main函数
(二)测试编码(Encoding)及译码(Decoding)函数
.
(二)测试印代码文件(Print)函数
(四)相关的根目录
五、总结
系统完成的功能:
本程序完成的功能是可以在信息发送端通过一个编码系统对待传数据预先编码,在信息接收端将传来的数据进行译码(复原)。
系统的不足:
本次课程设计,我认为还有很多不足,比如说不能把一个随机输入的字符串中不同字符作为叶子结点元素,把其在该字符串中出现的次数作为权值构造一个赫夫曼树,并得到各个叶子结点的赫夫曼编码和整个输入的字符串的赫夫曼编码,还有不能够顺利按题目要求写出相应的文件,将编码存储在tex文件中。
我的收获是:
通过本次实验,提高了自已调试程序的能力,充分体会到了在程序执行时的提示性输出的重要性,编写程序的时候,应先写出算法,再写程序,一段一段调试;此外,学编程一定要亲自动手,实践是检验真理正确性的唯一标准,不能眼高手低,还要学会归纳,发现编程的捷径,想着用更高效的方法去完成一个个任务。
6、附件(代码、部分图表)
#include
#include
#include
#include
constintUINT_MAX=1000;
charstr[50];
typedefstruct
{
intweight,K;
intparent,lchild,rchild;
}HTNode,*HuffmanTree;
typedefchar**HuffmanCode;
HuffmanTreeHT;
HuffmanCodeHC;
intw[50],i,j,n;
charz[50];
intflag=0;
intnumb=0;
structcou{
chardata;
intcount;
}cou[50];
intmin(HuffmanTreet,inti)
{
intj,flag;
intk=UINT_MAX;
for(j=1;j<=i;j++)
if(t[j].weightk=t[j].weight,flag=j;
t[flag].parent=1;
returnflag;
}
voidselect(HuffmanTreet,inti,int&s1,int&s2)
{
intj;
s1=min(t,i);
s2=min(t,i);
if(s1>s2)
{
j=s1;
s1=s2;
s2=j;
}
}
voidHuffmanCoding(HuffmanTree&HT,HuffmanCode&HC,int*w,intn)
{
intm,i,s1,s2,start;
intc,f;
HuffmanTreep;
char*cd;
if(n<=1)
return;
m=2*n-1;
HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));
for(p=HT+1,i=1;i<=n;++i,++p,++w)
{
p->weight=*w;
p->parent=0;
p->lchild=0;
p->rchild=0;
}
for(;i<=m;++i,++p)
p->parent=0;
for(i=n+1;i<=m;++i)
{
select(HT,i-1,s1,s2);
HT[s1].parent=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;
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));
strcpy(HC[i],&cd[start]);
}
free(cd);
}
intInputCode()
{
FILE*tobetran;
if((tobetran=fopen("tobetran.txt","w"))==NULL)
{
printf("不能打开文件\n");
return0;
}
printf("请输入你想要编码的字符\n");
gets(str);
fputs(str,tobetran);
printf("获取报文成功\n");
fclose(tobetran);
returnstrlen(str);
}
voidInitialization()
{inta,k,flag,len;
a=0;
len=InputCode();
for(i=0;i{k=0;flag=1;
cou[i-a].data=str[i];
cou[i-a].count=1;
while(i>k)
{
if(str[i]==str[k])
{
a++;
flag=0;
}
k++;
if(flag==0)
break;
}
if(flag)
{
for(j=i+1;j{if(str[i]==str[j])
++cou[i-a].count;}
}
}
n=len-a;
for(i=0;i{
printf("%d%d",i,cou[i].data);
printf("%d%d\n",i,cou[i].count);
}
for(i=0;i<=n;i++)
{*(z+i)=cou[i].data;
*(w+i)=cou[i].count;
}
HuffmanCoding(HT,HC,w,n);
printf("字符对应的编码为:
\n");
for(i=1;i<=n;i++)
{
puts(HC[i]);
}
printf("下面将哈夫曼编码写入文件\n...................\n\n");
FILE*htmTree;
charr[]={'','\0'};
if((htmTree=fopen("htmTree.txt","w"))==NULL)
{
printf("cannotopenfile\n");
return;
}
fputs(z,htmTree);
for(i=0;i{
fprintf(htmTree,"%6d",*(w+i));
fputs(r,htmTree);
}
for(i=1;i<=n;i++)
{
fputs(HC[i],htmTree);
fputs(r,htmTree);
}
fclose(htmTree);
printf("已将字符与对应编码写入根目录下文件htmTree.txt中\n\n");
}
voidEncoding()
{
printf("下面对目录下文件tobetran.txt中的字符进行编码\n");
FILE*tobetran,*codefile;
if((tobetran=fopen("tobetran.txt","rb"))==NULL)
{
printf("不能打开文件\n");
}
if((codefile=fopen("codefile.txt","wb"))==NULL)
{
printf("不能打开文件\n");
}
char*tran;
i=99;
tran=(char*)malloc(100*sizeof(char));
while(i==99)
{
if(fgets(tran,100,tobetran)==NULL)
{
printf("不能打开文件\n");
break;
}
for(i=0;*(tran+i)!
='\0';i++)
{
for(j=0;j<=n;j++)
{
if(*(z+j-1)==*(tran+i))
{
fputs(HC[j],codefile);
if(j>n)
{
printf("字符错误,无法编码!
\n");
break;
}
}
}
}
}
printf("编码工作完成\n\n编码写入目录下的codefile.txt中\n\n");
fclose(tobetran);
fclose(codefile);
free(tran);
}
voidDecoding()
{
printf("下面对根目录下文件codefile.txt中的字符进行译码\n");
FILE*codef,*txtfile;
if((txtfile=fopen("txtfile.txt","w"))==NULL)
{
printf("不能打开文件\n");
}
if((codef=fopen("codefile.txt","r"))==NULL)
{
printf("不能打开文件\n");
}
char*work,*work2,i2;
inti4=0,i,i3;
unsignedlonglength=10000;
work=(char*)malloc(length*sizeof(char));
fgets(work,length,codef);
work2=(char*)malloc(length*sizeof(char));
i3=2*n-1;
for(i=0;*(work+i-1)!
='\0';i++)
{
i2=*(work+i);
if(HT[i3].lchild==0)
{
*(work2+i4)=*(z+i3-1);
i4++;
i3=2*n-1;
i--;
}
elseif(i2=='0')i3=HT[i3].lchild;
elseif(i2=='1')i3=HT[i3].rchild;
}
*(work2+i4)='\0';
fputs(work2,txtfile);
printf("译码完成\n内容写入根目录下的文件txtfile.txt中\n\n");
free(work);
free(work2);
fclose(txtfile);
fclose(codef);
}
voidCode_printing()
{
printf("下面打印根目录下文件CodePrin.txt中编码字符\n");
FILE*CodePrin,*codefile;
if((CodePrin=fopen("CodePrin.txt","w"))==NULL)
{
printf("不能打开文件\n");
return;
}
if((codefile=fopen("codefile.txt","r"))==NULL)
{
printf("不能打开文件\n");
return;
}
char*work3;
work3=(char*)malloc(51*sizeof(char));
do
{
if(fgets(work3