huffman(哈夫曼)树编码译码-课程设计报告_第1页
huffman(哈夫曼)树编码译码-课程设计报告_第2页
huffman(哈夫曼)树编码译码-课程设计报告_第3页
huffman(哈夫曼)树编码译码-课程设计报告_第4页
huffman(哈夫曼)树编码译码-课程设计报告_第5页
已阅读5页,还剩33页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、精选优质文档-倾情为你奉上数据结构课程设计学 院: 信息科学与工程学院专 业: 计算机科学与技术 班 级: 计卓1601学 号: 学生姓名: 指导教师: 年 月 日题目名称一、实验内容哈夫曼编码译码系统【问题描述】用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编/译码系统。【基本要求】1)初始化。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树。2)

2、编码。利用已建好的哈夫曼树对输入英文进行编码,编码结果存储在数组中。3)译码。利用已建好的哈夫曼树将数组中的代码进行译码,结果存入一个字符数组。4)输出编码。将编码结果显示在终端上,每行50个代码。5)输出哈夫曼树。将哈夫曼树以直观的方式(树或凹入表形式)显示出来。【实现提示】用户界面可以设计为“菜单”方式,再加上一个“退出”功能。请用户键入一个选择功能符。此功能执行完毕后再显示此菜单,直至某次用户选择了“退出”为止。 参考教材P240-246 【选做内容】将哈夫曼树保存到文件中,编码和译码的结果也分别存放在两个文本文件中。二、数据结构设计储存结构struct HNodeType /字符结构体

3、类型int weight;/权int parent;/双亲位置int lchild;/左孩子int rchild;/右孩子char inf;/字符;struct HcodeType int bitMaxBit;/存储编码int start;/起始位置;三、算法设计1、在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode的大小设置为2n-1。求哈夫曼编码时使用一维结构数组HuffCode作为哈夫曼编码信息的存储。求哈夫曼编码实际上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点

4、的父节点回退到根结点,每回退一步,就走过了哈夫曼的一个分支,从而得到一位哈夫曼编码值。由于一个字符的哈夫曼编码就是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求的高位2、初始化为从键盘接受字符集大小n,以及n个字符和n个权值。3、建立哈夫曼编码为使用2中得到的数据按照教材中的构造哈弗曼的算法构造哈弗曼树,即将HuffNode数组中的各个位置的各个域都填上相关的值,并将这个结构体数组存于文件nodedata.dat中。void Creat_Haffmantree(int &n) /建树并输出树n+;HNodeT

5、ype *HaffNode=new HNodeType2*n-1;int i,j;int m1,m2,x1,x2;for(i=0; i<2*n-1; i+) /赋初值HaffNodei.weight=0;HaffNodei.parent=-1;HaffNodei.lchild=-1;HaffNodei.rchild=-1;HaffNodei.inf='0' for(i=0; i<n-1; i+) /输入字符及权值cout<<"请输入字符:"<<endl;cin>>HaffNodei.inf;cout<&l

6、t;"请输入该字符的权值:"<<endl;cin>>HaffNodei.weight;HaffNoden-1.inf=' '/最后一个为空格HaffNoden-1.weight=120;/空格权值for(i=0; i<n-1; i+) /构造哈夫曼树m1=m2=Maxvalue;x1=x2=0;for(j=0; j<n+i; j+) /找出最小和次小if(HaffNodej.parent=-1&&HaffNodej.weight<m1) m2=m1;x2=x1;m1=HaffNodej.weight;

7、x1=j; else if(HaffNodej.parent=-1&&HaffNodej.weight<m2) m2=HaffNodej.weight;x2=j;/合并Huffman树HaffNodex1.parent=n+i;HaffNodex2.parent=n+i;HaffNoden+i.weight=HaffNodex1.weight+HaffNodex2.weight;HaffNoden+i.lchild=x1;HaffNoden+i.rchild=x2;HaffNoden+i.inf=' '/输出树cout<<"显示存储的

8、哈弗曼树信息:"<<endl;cout<<" 权值 左孩子 右孩子 父节点"<<endl;for(i=0; i<2*n-1; i+) cout<<HaffNodei.inf<<" "cout<<setiosflags(ios:right)<<setw(4)<<HaffNodei.weight<<" "cout<<setiosflags(ios:right)<<setw(4)<<

9、HaffNodei.lchild<<" "cout<<setiosflags(ios:right)<<setw(4)<<HaffNodei.rchild<<" "cout<<setiosflags(ios:right)<<setw(4)<<HaffNodei.parent<<endl;/写入文件fstream outfile1;outfile1.open("E:nodedata.dat",ios:out|ios:trunc|io

10、s:binary);/建立进行写入的文件并清空之前数据 if(!outfile1) /没有创建成功则显示相应信息cout<<"nodedata.dat文件不能打开"<<endl;abort();for(i=0; i<2*n-1; i+) /将内存中从HaffNodei地址开始的sizeof(HaffNodei)的内容写入文件中outfile1.write(char*)&HaffNodei,sizeof(HaffNodei);outfile1.close ();/关闭文件delete HaffNode;4、 编码系统为从文件nodedat

11、a.dat中读入相关的字符信息进行哈弗曼编码,然后将结果存入code.dat中,同时将字符与0和1代码串的一一对应关系显示到屏幕上。void HaffCode(int &n) /哈夫曼编码HNodeType *HaffNode=new HNodeTypeMaxnode;/存储树HcodeType *HaffCode=new HcodeTypeMaxleaf;/存储编码HcodeType cd;int i,j,c,p;fstream in("E:nodedata.dat",ios:in|ios:binary);/打开文件in.read(char*)HaffNode,(

12、2*n-1)*sizeof(HNodeType);/从文件中读取树in.close();/关闭文件fstream outfile;outfile.open("E:codedata.dat",ios:out|ios:binary);/建立进行写入的文件for(i=0; i<n; i+) /进行编码 并向数组中从右向左写入编码cd.start=n-1;c=i;p=HaffNodec.parent;while(p!=-1) if(HaffNodep.lchild=c)cd.bitcd.start=0;elsecd.bitcd.start=1;cd.start-;c=p;p=

13、HaffNodec.parent;for(j=cd.start+1; j<n; j+)/ 向结构体数组存储编码HaffCodei.bitj=cd.bitj; HaffCodei.start=cd.start;for(i=0; i<n; i+) /向文件中存取数据outfile<<HaffNodei.inf;for(j=HaffCodei.start+1; j<n; j+)outfile<<HaffCodei.bitj;cout<<"字符信息-编码信息"<<endl;for(i=0; i<n; i+) c

14、out<<HaffNodei.inf<<"-"for(j=HaffCodei.start+1; j<n; j+)/输出编码cout<<HaffCodei.bitj;/编码信息01串cout<<endl; outfile.close ();/关闭文件cout<<"请输入要编码的字符串,基本元素为("for(i=0; i<n; i+)cout<<HaffNodei.inf<<","cout<<")"<<

15、;endl;char inf100;/定义输入字符存放数组getchar();gets(inf);/读取屏幕字符int f=strlen(inf);fstream outfile1;outfile1.open("E:code.dat",ios:out|ios:binary);/建立进行写入的文件if(!outfile1) cout<<"code.dat文件不能打开!"<<endl;abort(); else cout<<endl; cout<<"字符串编码后为:n"int num=0;f

16、or(int x=0; x<f; x+) /输出文本编码for(i=0; i<n; i+) if(infx=HaffNodei.inf) for(j=HaffCodei.start+1; j<n; j+) outfile1.write(char*)&HaffCodei.bitj,sizeof(HaffCodei.bitj);cout<<HaffCodei.bitj;num+;if(num%50=0) cout<<endl; cout<<endl;cout<<endl;cout<<"编译后的代码串已经

17、存入code.dat文件中!"<<endl;cout<<endl;outfile1.close();delete HaffNode;delete HaffCode;5、 译码系统为接收需要译码的0、1代码串,按照3中建立的编码规则将其翻译成字符集中字符所组成的字符串形式,存入文件textfile.dat,同时将翻译的结果在屏幕上打印输出。接受0、1代码串有两种形式,一种是直接输入,一种是从文件中读取。void decode( int &n) int i;HNodeType *HaffNode=new HNodeType2*n-1;fstream inf

18、ile1;infile1.open("E:nodedata.dat",ios:in|ios:binary);/打开文件if(!infile1) cout<<"nodedata.dat文件不能打开"<<endl;abort();for(i=0; i<2*n-1; i+)/从文件里读出Huffman树infile1.read(char*)&HaffNodei,sizeof(HNodeType);infile1.close();/关闭int tempcode100;/定义一个数组存放01串int num=0;for(i=0

19、; i<100; i+)/数组初始化tempcodei=-1;HcodeType *Code=new HcodeTypen;cout<<"请选择要做的操作:"<<endl;cout<<"4.输入01串解码"<<endl;cout<<"5.从文件中解码"<<endl;char q;cin>>q;while(q!='4'&&q!='5') cout<<"输入错误请重新输入"

20、;cin>>q;switch(q) case '4': cout<<"请输入要解码的0,1串(按2结束输入):"<<endl;i=0;char a;while(1)cin>>a;if(a!='0'&&a!='1'&&a!='2')cout<<"输入错误,请重新输入n" else break;if(a='0') tempcodei=0;else if(a='1')temp

21、codei=1;else if(a='2') tempcodei=2;while(tempcodei=0|tempcodei=1)i+;num=i; while(1)cin>>a;if(a!='0'&&a!='1'&&a!='2')cout<<"输入错误,请重新输入n" else break;if(a='0') tempcodei=0;else if(a='1')tempcodei=1;else if(a='2

22、9;) tempcodei=2;cout<<"输入的编码为:n"for(i=0;i<num;i+)cout<<tempcodei;cout<<endl;int m=2*n-2;i=0;cout<<"译码后为:"<<endl;fstream outfile;outfile.open("E:textfile.txt",ios:out);/打开存放翻译结果的文件if(!outfile) cout<<"textfile.txt文件不能打开!"&l

23、t;<endl;abort();while(i<num) while(HaffNodem.lchild!=-1&&HaffNodem.rchild!=-1) /判断是不是叶子节点if(tempcodei=0) / 0为向左走m=HaffNodem.lchild;i+; else if(tempcodei=1) /1为向右走m=HaffNodem.rchild;i+;cout<<HaffNodem.inf;/输出叶子节点即翻译出的字符outfile<<HaffNodem.inf;/写入文件m=2*n-2;cout<<endl;out

24、file.close();cout<<"译码后的结果已经存入textfile.txt中!"<<endl<<endl;delete HaffNode;/释放break;case '5': fstream infile2;/读编码infile2.open("E:code.dat",ios:in|ios:binary);while(!infile2.eof() infile2.read(char*)&tempcodenum,sizeof(tempcodenum);num+;infile2.close(

25、);num-;cout<<"从文件中读出的编码为"<<endl;for(i=0; i<num; i+) cout<<tempcodei;if(i+1)%50=0) cout<<endl;/每输出50个编码换行cout<<endl;int m=2*n-2;i=0;cout<<endl;cout<<"译码后为:"<<endl;fstream outfile;outfile.open("E:textfile.txt",ios:out);if

26、(!outfile) cout<<"textfile.txt文件不能打开!"<<endl;abort();while(i<num)/ 从根节点0向左1向右while(HaffNodem.lchild!=-1&&HaffNodem.rchild!=-1) if(tempcodei=0) m=HaffNodem.lchild;i+; else if(tempcodei=1) m=HaffNodem.rchild;i+;cout<<HaffNodem.inf;outfile<<HaffNodem.inf;m=2

27、*n-2;cout<<endl;outfile.close();/关闭文件cout<<"译码后的结果已经存入textfile.txt中!"<<endl;delete HaffNode;/释放break;四、测试数据及程序运行情况用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”。字符ABCDEFGHIJKLM频度6413223210321154757153220字符NOPQRSTUVWXYZ频度5763151485180238181161图1程序运行界

28、面:图1:程序开始界面 图2:程序初始化输出Huffman树图2图4图3图3:编码信息输出 图4:对字符串编码并输出图5:解码系统 图6:解码系统图5图6对01串译码输出并保存到文件读出01串(文件或键入)输出字符与编码对应关系对已输入的字符编码赋初值for(i=0; i<2*n-1; i+)输入字符和权值建树读入一串字符(文件或键入)输出Huffman树对字符串编码输出并保存到文件五、实验过程中出现的问题及解决方法1、用最小堆建立Huffman树出现太多错误且过于繁琐不易更改,故改用结构体数组建树。2、Huffman树输出时,权值大小不同导致显示错乱,故改用输出流控制。3、编码时出现非

29、01字码,原因是定义的存储空间太小。后多次实验确定合适大小。4、编码时读到空格会导致系统停止,后给空格定义了权值。5、文件使用txt格式存放数据读取时出现乱码,故改为dat文件。6、当输出非法字符是会导致系统错乱,后通过修改字符读入方式和循环判定解决问题六、自我评析与总结 通过本次课程设计,我对哈夫曼树及哈夫曼编码有了更深刻的理解。同时对C+的编程以及算法的实现和文件的读写产生了比以往更大的兴趣,还学到了许多在处理程序bug以及程序美化时的技巧和方法。如在处理数据时要分配合理的空间,也要及时释放空间。从刚开始一点头绪都没有,到后来一步步编写成功,查阅了好多资料,也询问了好多同学。根据老师要求,

30、在译码处不单实现了从键盘读入,同时也实现了从文件读入。通过这次实验我积累了更多编程的经验。程序有很多不足的地方,例如程序健壮性不好,二进制读写容易出错等等。从文件中修改二进制编码功能尝试了很久还是没能完成,没有能实现哈夫曼树的图形化输出,这些都是我们的遗憾。但是在程序的编写中,我们也完善了很多问题,添加了一些功能,在一定程度上提高了程序的健壮性。每解决一个问题,我们都会发自内心的感到高兴,这大概就是写程序的乐趣。通过这次课程设计,让我更好的理解了本学期数据结构的课程知识,也大大提高了我们用c+编程的能力,我们更加注重添加注释,增强代码的可读性,这都是我们在本次课程设计中取得的进步。七、参考文献

31、 数据结构(面向对象方法与C+语言描述)殷人昆 清华大学出版社数据结构 严蔚敏,吴伟民 清华大学出版社双语版C+语言程序设计 电子工业出版社百度百科 CSDN社区/源代码#include<iostream>#include<fstream>#include<string.h>#include<stdlib.h>#include<iomanip>using namespace std;#define MaxBit 50#define Maxvalue 1000#define Maxleaf 50#define Maxnode Maxle

32、af*2-1struct HNodeType /字符结构体类型int weight;/权int parent;/双亲位置int lchild;/左孩子int rchild;/右孩子char inf;/字符;struct HcodeType int bitMaxBit;/存储编码int start;/起始位置;void Creat_Haffmantree(int &n) /建树并输出树n+;HNodeType *HaffNode=new HNodeType2*n-1;int i,j;int m1,m2,x1,x2;for(i=0; i<2*n-1; i+) /赋初值HaffNode

33、i.weight=0;HaffNodei.parent=-1;HaffNodei.lchild=-1;HaffNodei.rchild=-1;HaffNodei.inf='0' for(i=0; i<n-1; i+) /输入字符及权值cout<<"请输入字符:"<<endl;cin>>HaffNodei.inf;cout<<"请输入该字符的权值:"<<endl;cin>>HaffNodei.weight;HaffNoden-1.inf=' '/最

34、后一个为空格HaffNoden-1.weight=120;/空格权值for(i=0; i<n-1; i+) /构造哈夫曼树m1=m2=Maxvalue;x1=x2=0;for(j=0; j<n+i; j+) /找出最小和次小if(HaffNodej.parent=-1&&HaffNodej.weight<m1) m2=m1;x2=x1;m1=HaffNodej.weight;x1=j; else if(HaffNodej.parent=-1&&HaffNodej.weight<m2) m2=HaffNodej.weight;x2=j;/合

35、并Huffman树HaffNodex1.parent=n+i;HaffNodex2.parent=n+i;HaffNoden+i.weight=HaffNodex1.weight+HaffNodex2.weight;HaffNoden+i.lchild=x1;HaffNoden+i.rchild=x2;HaffNoden+i.inf=' '/输出树cout<<"显示存储的哈弗曼树信息:"<<endl;cout<<" 权值 左孩子 右孩子 父节点"<<endl;for(i=0; i<2*

36、n-1; i+) cout<<HaffNodei.inf<<" "cout<<setiosflags(ios:right)<<setw(4)<<HaffNodei.weight<<" "cout<<setiosflags(ios:right)<<setw(4)<<HaffNodei.lchild<<" "cout<<setiosflags(ios:right)<<setw(4)<<

37、HaffNodei.rchild<<" "cout<<setiosflags(ios:right)<<setw(4)<<HaffNodei.parent<<endl;/写入文件fstream outfile1;outfile1.open("E:nodedata.dat",ios:out|ios:trunc|ios:binary);/建立进行写入的文件并清空之前数据 if(!outfile1) /没有创建成功则显示相应信息cout<<"nodedata.dat文件不能打开&q

38、uot;<<endl;abort();for(i=0; i<2*n-1; i+) /将内存中从HaffNodei地址开始的sizeof(HaffNodei)的内容写入文件中outfile1.write(char*)&HaffNodei,sizeof(HaffNodei);outfile1.close ();/关闭文件delete HaffNode;void HaffCode(int &n) /哈夫曼编码HNodeType *HaffNode=new HNodeTypeMaxnode;/存储树HcodeType *HaffCode=new HcodeTypeMa

39、xleaf;/存储编码HcodeType cd;int i,j,c,p;fstream in("E:nodedata.dat",ios:in|ios:binary);/打开文件in.read(char*)HaffNode,(2*n-1)*sizeof(HNodeType);/从文件中读取树in.close();/关闭文件fstream outfile;outfile.open("E:codedata.dat",ios:out|ios:binary);/建立进行写入的文件for(i=0; i<n; i+) /进行编码 并向数组中从右向左写入编码cd.

40、start=n-1;c=i;p=HaffNodec.parent;while(p!=-1) if(HaffNodep.lchild=c)cd.bitcd.start=0;elsecd.bitcd.start=1;cd.start-;c=p;p=HaffNodec.parent;for(j=cd.start+1; j<n; j+)/ 向结构体数组存储编码HaffCodei.bitj=cd.bitj; HaffCodei.start=cd.start;for(i=0; i<n; i+) /向文件中存取数据outfile<<HaffNodei.inf;for(j=HaffCo

41、dei.start+1; j<n; j+)outfile<<HaffCodei.bitj;cout<<"字符信息-编码信息"<<endl;for(i=0; i<n; i+) cout<<HaffNodei.inf<<"-"for(j=HaffCodei.start+1; j<n; j+)/输出编码cout<<HaffCodei.bitj;/编码信息01串cout<<endl; outfile.close ();/关闭文件cout<<"

42、;请输入要编码的字符串,基本元素为("for(i=0; i<n; i+)cout<<HaffNodei.inf<<","cout<<")"<<endl;char inf100;/定义输入字符存放数组getchar();gets(inf);/读取屏幕字符int f=strlen(inf);fstream outfile1;outfile1.open("E:code.dat",ios:out|ios:binary);/建立进行写入的文件if(!outfile1) cout&l

43、t;<"code.dat文件不能打开!"<<endl;abort(); else cout<<endl; cout<<"字符串编码后为:n"int num=0;for(int x=0; x<f; x+) /输出文本编码for(i=0; i<n; i+) if(infx=HaffNodei.inf) for(j=HaffCodei.start+1; j<n; j+) outfile1.write(char*)&HaffCodei.bitj,sizeof(HaffCodei.bitj);co

44、ut<<HaffCodei.bitj;num+;if(num%50=0) cout<<endl; cout<<endl;cout<<endl;cout<<"编译后的代码串已经存入code.dat文件中!"<<endl;cout<<endl;outfile1.close();delete HaffNode;delete HaffCode;/*译码系统*/void decode( int &n) int i;HNodeType *HaffNode=new HNodeType2*n-1;f

45、stream infile1;infile1.open("E:nodedata.dat",ios:in|ios:binary);/打开文件if(!infile1) cout<<"nodedata.dat文件不能打开"<<endl;abort();for(i=0; i<2*n-1; i+)/从文件里读出Huffman树infile1.read(char*)&HaffNodei,sizeof(HNodeType);infile1.close();/关闭int tempcode100;/定义一个数组存放01串int num

46、=0;for(i=0; i<100; i+)/数组初始化tempcodei=-1;HcodeType *Code=new HcodeTypen;cout<<"请选择要做的操作:"<<endl;cout<<"4.输入01串解码"<<endl;cout<<"5.从文件中解码"<<endl;char q;cin>>q;while(q!='4'&&q!='5') cout<<"输入错误

47、请重新输入"cin>>q;switch(q) case '4': cout<<"请输入要解码的0,1串(按2结束输入):"<<endl;i=0;char a;while(1)cin>>a;if(a!='0'&&a!='1'&&a!='2')cout<<"输入错误,请重新输入n" else break;if(a='0') tempcodei=0;else if(a='1

48、')tempcodei=1;else if(a='2') tempcodei=2;while(tempcodei=0|tempcodei=1)i+;num=i; while(1)cin>>a;if(a!='0'&&a!='1'&&a!='2')cout<<"输入错误,请重新输入n" else break;if(a='0') tempcodei=0;else if(a='1')tempcodei=1;else if(a

49、='2') tempcodei=2;cout<<"输入的编码为:n"for(i=0;i<num;i+)cout<<tempcodei;cout<<endl;int m=2*n-2;i=0;cout<<"译码后为:"<<endl;fstream outfile;outfile.open("E:textfile.txt",ios:out);/打开存放翻译结果的文件if(!outfile) cout<<"textfile.txt文件不能打

50、开!"<<endl;abort();while(i<num) while(HaffNodem.lchild!=-1&&HaffNodem.rchild!=-1) /判断是不是叶子节点if(tempcodei=0) / 0为向左走m=HaffNodem.lchild;i+; else if(tempcodei=1) /1为向右走m=HaffNodem.rchild;i+;cout<<HaffNodem.inf;/输出叶子节点即翻译出的字符outfile<<HaffNodem.inf;/写入文件m=2*n-2;cout<<endl;outfile.close();cout<<"译码后的结果已经存入textfile.txt中!"<<endl<<endl;delete HaffNode;/释放b

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论