哈弗曼编码译码器.docx

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

哈弗曼编码译码器.docx

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

哈弗曼编码译码器.docx

哈弗曼编码译码器

1需求分析

1、利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。

对于双工信道(既可以双向传输信息的信道),每端都需要一个完整的编/译码系统。

2、本次课程设计就是要设计一个哈夫曼编码/译码系统,对一个文本文件中的字符进行哈夫曼编码,生成编码文件(压缩文件,后缀.cod),反过来,可将一个压缩文件译码还原为一个文件(.txt)

2题目要求

1.输入一个待压缩的文件名,统计文本文件中的各字符的个数作为权值,生成哈夫曼树。

2.将文本文件利用哈夫曼树进行编码,生成压缩文件(.cod)

3.输入一个待解压文件名称,并利用相应的哈夫曼树将编码序列译码。

4.显示指定的压缩文件和文本文件。

3运行环境(软、硬件环境)

windowsXP/windows2000

4开发工具和编程语言

开发工具:

MicrosoftVisualC++;

编程语言:

C++;

5详细设计

(1)首先,对一些基本的基本输入输出函数,字符串函数,动态存储分配等函数进行定义:

#include//包含基本输入输出函数

#include//包含字符串函数

#include//包含exit()及动态存储分配等函数

#include//C++

#include

#include

对输入的字符数进行定义:

(用N代表能够编码的最大字符数)

例如:

设输入编码的最大的字符数为100,则具体的操作如下:

#defineN100

(2)然后,定义字符和其存储信息,定义哈夫曼树各结点的存储信息,具体的操作如下:

structcharacter{//定义字符

charcha;//用来保存各字符信息

intcount;//存放字符的权值

}R[N];

structHuffmanNode{//定义哈夫曼树各结点

intweight;//存放结点的权值

intparent;//记录结点父亲位置

intlchild,rchild;//分别存放该结点的左、右孩子的所在单元的编号

}HTNode,*Node;

intNum;//记录所要编译的文本中的字符的个数

char*Info;//存放结点的字符信息

chartoken[10];//用来存储原文件名

charfile_name[10],file_name1[10];//用来存储目标文件名

(3)统计文本文件中的各字符的个数作为权值,生成哈夫曼树。

在操作中要首先对哈夫曼树的初始化:

用函数voidInitialization()来完成;具体的操作如下:

voidInitialization()

{

inti,j,pos1,pos2,max1,max2;

Node=newHuffmanNode[2*Num-1];//Num权值对应的哈夫曼树中的结点总数为2*Num-1个

Info=newchar[2*Num-1];

for(i=0;i

Info[i]=R[i].cha;//传送字符信息

Node[i].weight=R[i].count;//传送权值

Node[i].parent=-1;//为根结点

Node[i].lchild=-1;//无左孩子

Node[i].rchild=-1;//无右孩子

}

for(i=Num;i<2*Num-1;i++)//表示需做Num-1次合并

{pos1=-1;

pos2=-1;//分别用来存放当前最小值和次小值的所在单元编号

max1=32767;//32767为整型数的最大值

max2=32767;//分别用来存放当前找到的最小值和次小值

for(j=0;j

if(Node[j].parent==-1)//是否为根结点

if(Node[j].weight

max2=max1;//原最小值变为次小值

max1=Node[j].weight;//存放最小值

pos2=pos1;//修改次小值所在单元编号

pos1=j;//修改最小值所在单元编号

}

else

if(Node[j].weight

max2=Node[j].weight;//存放次小值

pos2=j;//修改次小值所在的单元编号

}

Node[pos1].parent=i;//修改父亲位置

Node[pos2].parent=i;

Node[i].lchild=pos1;//修改儿子位置

Node[i].rchild=pos2;

Node[i].parent=-1;Node[i].weight=Node[pos1].weight+Node[pos2].weight;

}

(4)将文本文件利用哈夫曼树进行编码,生成压缩文件(.cod)完成该要求的函数操作和算法如下:

voidEncoder()//编码

{

if(Node==NULL){//哈夫曼树不在内存,从文件hfmTree中读入

ifstreamfip;//以二进制方式打开hfmTree.dat文件

fip.open("hfmTree.dat",ios:

:

in);//ios:

:

in

if(fip.fail()){//文件打开失败

cout<<"文件打开失败!

\n";

return;//结束本函数

}

fip.read((char*)&Num,sizeof(Num));//读取叶子数

Info=newchar[Num];

Node=newHuffmanNode[2*Num-1];

for(inti=0;i

fip.read((char*)&Info[i],sizeof(Info[i]));

for(i=0;i<2*Num-1;i++)//读取结点信息

fip.read((char*)&Node[i],sizeof(Node[i]));

}

char*Tree;//用于存储需编码内容

inti=0;

ifstreamfip1(token);

if(fip1.fail())//文件不存在

{cout<<"文件打开失败!

\n";

return;//结束本函数

}

charch;

intk=0;

while(fip1.get(ch)){

k++;}//计算文件中代码长度

fip1.close();

Tree=newchar[k+1];

ifstreamfip2(token);

k=0;

while(fip2.get(ch))

{

Tree[k]=ch;//读取文件内容,并存到Tree中

k++;

}

fip2.close();

cout<<"需编码内容为:

";

for(i=0;i

cout<

cout<<"\n";

cout<<"请输入存储编码的文件名(包括后缀名(.cod)):

";

cin>>file_name1;

ofstreamfop(file_name1,ios:

:

trunc);//存储编码后的代码,并覆盖原文件

i=0;k=0;

char*code;

code=newchar[Num];//为所产生编码分配容量为Num的存储空间

cout<<"文件进行编码后为:

";

while(Tree[k]!

='#')//对每一个字符编码

{intj,start=0;

for(i=0;i

if(Info[i]==Tree[k])//求出该文字所在单元的编号

break;

j=i;

while(Node[j].parent!

=-1)//结点j非树根

{j=Node[j].parent;//非结点j的双亲结点

if(Node[j].lchild==i)//是左子树,则生成代码0

code[start++]='0';

else//是右子树,则生成代码1

code[start++]='1';

i=j;

}code[start]='\0';//置串结束符

for(i=0;i

j=code[i];

code[i]=code[start-i-1];

code[start-i-1]=j;

}

i=0;

while(code[i]!

='\0'){//存储代码

cout<

fop<

i++;

}//cout<<"";

k++;

}

fop.close();

cout<<"\n编码成功!

且已存到文件"<

\n\n";

}

(5)输入一个待解压文件名称,并利用相应的哈夫曼树将编码序列译码。

完成译码所用到的函数操作和算法如下:

voidDecoder()//译码

{

inti=0,k=0;

intj=Num*2-1-1;//表示从根结点开始往下搜索

char*BitStr;

cout<<"请输入需要进行译码的文件名(包括后缀名(.cod)):

";

cin>>file_name1;

ifstreamfip1(file_name1);//利用已建好的哈夫曼树将文件中的代码进行译码

if(fip1.fail())//文件打开失败,还未编码

{cout<<"请先编码!

\n";

return;

}

charch;

while(fip1.get(ch)){

k++;//计算文件中代码长度

}

fip1.close();

BitStr=newchar[k+1];

ifstreamfip2(file_name1);

k=0;

while(fip2.get(ch))

{

BitStr[k]=ch;//读取文件内容

k++;

}

fip2.close();

BitStr[k]='\0';//结束标志符

if(Node==NULL)//还未建哈夫曼树

{cout<<"请先编码!

\n";

return;

}

cout<<"请输入储存译码后的文件名(包括后缀名(.txt)):

";

cin>>file_name;

ofstreamfop(file_name);//将字符形式的编码文件写入文件中

if(fop.fail())//文件不存在

{cout<<"文件打开失败!

\n";

return;//结束本函数

}cout<<"经译码,原内容为:

";

while(BitStr[i]!

='\0')

{if(BitStr[i]=='0')

j=Node[j].lchild;//往左走

else

j=Node[j].rchild;//往右走

if(Node[j].rchild==-1)//到达叶子结点

{cout<

fop<

j=Num*2-1-1;//表示重新从根结点开始往下搜索

}

i++;

}

fop.close();

cout<<"\n译码成功!

且已存到文件"<

\n\n";

}

6调试分析

在程序没有语法和逻辑错误的时候,进行运行的时候,一直不能够输出结果,经过认真的查找才发现,在程序中要求,建立的文本中的内容要以“#”结尾,而在现实建立的文本中的内容最后忘了以#结尾。

修改后程序能够正确的运行。

在程序调试成功后,建立一个命名为:

“a.txt”的文本,在文本中放入“yanglinsen#”一串字符作为测试数据,然后运行程序,经过运行测试程序能够输出结果,且正确的统计出字符的个数及权值:

字符:

yanglise

权值:

11311111

而且,能构成产生其相应的哈夫曼树,

然后,进行编码,在输入存储编码的文件名:

“a.cod”后,文件进行编码后为:

11101111100000010101001111010编码成功,而且已存到文件“a.cod”中!

经验证确实生成a.cod文件。

最后,进行译码,先输入要进行译码的文件名“a.cod”,然后再命名一个为“ase.txt”的文件来存储译码后的内容,经译码,原内容为:

yanglinsen译码成功,且已存到文件ase.txt中!

经验证确实生成ase.txt文件。

经过上个数据的测试,该程序能够正确地完成题目所要求的条件,但是,再输入一组数据:

while(ch!

='{or(i=Num;i<2*Num-1;i++)

t=0;ad{pos1=-1;if(ch==R[n].cha){a

R[n]d.count++;t+f+;}gj

if(t==0)i++;R[i].cha=chR[i].count=1;

ch=fgetc(fp)klxc}

则在运行中出现错误,能够统计出其字符及权值,但不能进行编码和译码,经过思考发现在程序中,在定义输入能够编码的最大的字符数

#defineN10

而在上一组数据中,字符的个数超过了10,所以不能够进行操作,出现运行错误,把程序中的“N”的定义值改成100,再进行运行测试,则能够输出正确的结果。

7测试结果

测试数据

(1)

首先,建立一个文本,命名为“yang.txt”在文本中放入

Whereareyoucomefrom?

IcomefromChina!

Wemaytalkofbeautifulthings,

butbeautyitselfisabstract!

#

做为测试数据。

运行结果:

(1)字符个数及其权值:

(2)哈夫曼树的生成:

(3)将文本内容利用哈夫曼树进行编码,生成压缩文件(.cod)

(4)输入一个待解压文件名称,并利用相应的哈夫曼树将编码序列译码。

测试数据2:

建立一个文本“lin.txt”在这个文本里放入“河南工业大学#”作为测试数据。

运行结果:

(1)字符个数及其权值及哈夫曼树的生成:

(2)将文本内容利用哈夫曼树进行编码,生成压缩文件(.cod)及输入一个待解压文件名称,并利用相应的哈夫曼树将编码序列译码。

8参考文献

[1]严蔚敏,数据结构(c语言版),北京:

清华大学出版社,2002,144~148

[2]WilliamFordWilliamTopp,数据结构C++语言描述,北京:

清华大学出版社,1998.11,421~451

[3]谭浩强,C程序设计(第二版),清华大学出版社,1999.12

心得体会

1、经过这次课程设计实验,更好的掌握了数据结构中的哈夫曼树,并对哈夫曼树有了深一步的了解,认识到了哈夫曼编码和译码在现实生活中的巨大作用。

2、掌握了构建生成哈夫曼树,统计其结点和权值的函数和算法,也掌握了哈夫曼编码的函数voidEncoder()和译码voidDecoder(),对哈夫曼编码/译码的算法也有了进一步的了解,也更熟悉了文件的操作。

3、通过这次实验认识到,对一些关键的算法理解分析透彻,这样在程序调试的时候可以剩不少时间。

4、在完成实验的过程中认识到认真仔细的重要性,在实验过程中,由于粗心大意,没有认真的读程序,出现了一些错误,浪费了不少的时间。

5、经过这次课程设计,对我的读,写程序的能力和发现问题和解决问题的能力都有一定的提高。

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

当前位置:首页 > PPT模板 > 图表模板

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

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