1、1数据结构课程设计报告设 计 题 目 哈 夫 曼 (Huffman) 编/译 码 器 学 院 名 称 信 息 工 程 学 院 专 业 班 级 12 计 本 2 姓 名 张 翠 翠 学 号 1212210217 _2题目:哈夫曼(Huffman) 编/译码器一、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编/译码系统。二、设计目标帮助学生熟练掌握树的应
2、用和基本操作,重点掌握二叉树的存储,这里以哈夫曼树为设计目标进一步提高学生的设计能力及对树的理解。三、任务要求一个完整的系统应具有以下功能:1) I:初始化(Initialization)。从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree中。2) E:编码(Encoding)。利用以建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。 3) D:译码(Decoding)。利用已建好的哈夫曼树将文件CodeFile中的代码进行译码,结果存入文件TextFile中。 4)
3、 P:印代码文件(Print)。将文件CodeFile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件CodePrin中。 5) T:印哈夫曼树(Tree Printing)。将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。3四、需求分析利用哈夫曼树(Huffman)编/译码(一)、初始化哈夫曼树(二)、建立哈夫曼树(三)、对哈夫曼树进行编码(四)、输出对应字符的编码(五)、译码过程五、概要设计哈夫曼树的存储结构描述typedef structunsigned int weight;unsign
4、ed int parent, lchild, rchild;HTNode, *HuffmanTree; 哈弗曼树的算法void CreateHT(HTNode ht,int n) /调用输入的数组ht,和节点数nint i,k,lnode,rnode;int min1,min2;for (i=0;i#include /要用system 函数要调用的头文件#include /用getch()要调用的头文件#include #define N 50 /义用N 表示50 叶节点数#define M 2*N-1 /用M表示节点总数 当叶节点数位n时总节点数为2n-1#define MAXSIZE 10
5、0typedef structchar data; /结点值int weight; /权值int parent; /双亲结点int lchild; /左孩子结点int rchild; /右孩子结点16HTNode; typedef structchar cdN; /存放哈夫曼码int start; /从start开始读cd中的哈夫曼码HCode;void CreateHT(HTNode ht,int n) /调用输入的数组ht,和节点数nint i,k,lnode,rnode;int min1,min2;for (i=0;i2*n-1;i+) hti.parent=hti.lchild=hti
6、.rchild=-1; /所有结点的相关域置初值-1for (i=n;i2*n-1;i+) /构造哈夫曼树min1=min2=32767; /int的范围是 -3276832767lnode=rnode=-1; /lnode和rnode记录最小权值的两个结点位置for (k=0;k=i-1;k+)if (htk.parent=-1) /只在尚未构造二叉树的结点中查找if (htk.weightmin1) /若权值小于最小的左节点的权值min2=min1;rnode=lnode;min1=htk.weight;lnode=k;17else if (htk.weightmin2)min2=htk.
7、weight;rnode=k;htlnode.parent=i;htrnode.parent=i; /两个最小节点的父节点是ihti.weight=htlnode.weight+htrnode.weight; /两个最小节点的父节点权值为两个最小节点权值之和hti.lchild=lnode;hti.rchild=rnode; /父节点的左节点和右节点void CreateHCode(HTNode ht,HCode hcd,int n)int i,f,c;HCode hc;for (i=0;in;i+) /根据哈夫曼树求哈夫曼编码hc.start=n;c=i;f=hti.parent;while
8、 (f!=-1) /循序直到树根结点结束循环if (htf.lchild=c) /处理左孩子结点hc.cdhc.start-=0;18else /处理右孩子结点hc.cdhc.start-=1;c=f;f=htf.parent;hc.start+; /start指向哈夫曼编码hc.cd中最开始字符hcdi=hc;void DispHCode(HTNode ht,HCode hcd,int n) /输出哈夫曼编码的列表int i,k;printf(“ 输出哈夫曼编码:n“); for (i=0;in;i+) /输出data中的所有数据,即A-Zprintf(“ %c:t“,hti.data);
9、for (k=hcdi.start;k=n;k+) /输出所有data中数据的编码printf(“%c“,hcdi.cdk); printf(“n“);void editHCode(HTNode ht,HCode hcd,int n) /编码函数char stringMAXSIZE; 19int i,j,k;scanf(“%s“,string); /把要进行编码的字符串存入string 数组中printf(“n输出编码结果:n“);for (i=0;stringi!=#;i+) /#为终止标志for (j=0;jn;j+)if(stringi=htj.data) /循环查找与输入字符相同的编号
10、,相同的就输出这个字符的编码for (k=hcdj.start;k=n;k+)printf(“%c“,hcdj.cdk);break; /输出完成后跳出当前 for循环void deHCode(HTNode ht,HCode hcd,int n) /译码函数char codeMAXSIZE;int i,j,l,k,m,x;scanf(“%s“,code); /把要进行译码的字符串存入code数组中while(code0!=#)20for (i=0;in;i+)m=0; /m为想同编码个数的计数器for (k=hcdi.start,j=0;k=n;k+,j+) /j为记录所存储这个字符的编码个数
11、if(codej=hcdi.cdk) /当有相同编码时m值加1m+;if(m=j) /当输入的字符串与所存储的编码字符串个数相等时则输出这个的data 数据printf(“%c“,hti.data);for(x=0;codex-1!=#;x+) /把已经使用过的code数组里的字符串删除codex=codex+j;void main()int n=26,i;char orz,back,flag=1;char str=A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z; /初始化21int fnum=186,64,13,22,32,103,21
12、,15,47,57,1,2,32,20,57,63,15,1,48,51,80,23,8,18,1,16; /初始化HTNode htM; /建立结构体HCode hcdN; /建立结构体for (i=0;in;i+) /把初始化的数据存入ht结构体中hti.data=stri;hti.weight=fnumi;while (flag) /菜单函数,当flag为0时跳出循环printf(“n“);printf(“ *“);printf(“n * A-显示编码 *“);printf(“n * B-进行编码 *“);printf(“n * C-进行译码 *“);printf(“n * D-退出 *
13、n“);printf(“ *“);printf(“n“);printf(“ 请输入选择的编号 :“);scanf(“%c“,switch(orz)case a:case A:22system(“cls“); /清屏函数CreateHT(ht,n);CreateHCode(ht,hcd,n);DispHCode(ht,hcd,n);printf(“n按任意键返回.“);getch();system(“cls“);break;case b:case B:system(“cls“);printf(“请输入要进行编码的字符串 (以#结束):n“);editHCode(ht,hcd,n);printf(
14、“n按任意键返回.“);getch();system(“cls“);break;case c:case C:system(“cls“);DispHCode(ht,hcd,n);printf(“请输入编码 (以#结束):n“);deHCode(ht,hcd,n);printf(“n按任意键返回.“);getch();system(“cls“);break;23case d:case D:flag=0;break;default:system(“cls“);:该程序的截图:初始化界面截图如下选A时的显示结果截图如下24选择B时的显示结果截图如下选C时的显示结果截图如下25十一、使用说明(给出软件如
15、何使用,使用时的注意事项)VC+6.0编程环境使用1、 VC+6.0程序启动 2、新建工程Project3、 设定工程Project名称、保存位置 4、 设定工程Project的类型 5、 工程Project的描述信息生成6、 空工程Project建立完毕7) 向工程Project中添加(新建)源代码文件的类型、名称、保存位置 8、设定源代码文件的类型、名称9、 源代码文件被添加到工程中 10、在源代码文件中添加程序代码11、程序代码编译完成后编译、链接过程注意事项: 26(1) 一个工程project中可以有多个源文件(.cpp)、多个头文件(.h);但这些源代码文件中只能出现一个main函
16、数,作为整个程序运行的入口; (2)必须关闭前一次程序运行结果窗口,才能进行下一次程序运行; (3)书写标识符时,忽略了大小写字母的区别。 (4 ) 忘记加分号 (5) 多加分号十二、课程设计总结本次课程设计的题目是:哈夫曼(Huffman)编/译码器。通过这次课程设计,我了解到自己在编写程序方面还有很多不足,在实践过程中老师给了我很大的帮助。在这次课程设计中,虽然不会成功的编写一个完整的程序,但是在看程序的过程中,不断的上网查资料以及翻阅相关书籍,通过不断的模索,测试,发现问题,解决问题和在老师的帮助下一步一步慢慢的正确运行程序,终于完成了这次课程设计,虽然这次课程设计结束了但是总觉得自已懂得的知识很是不足,学无止境,以后还会更加的努力深入的学习。