1、目录第 1 章 问题描述假设某文档只包含 26 个英文字母,应用哈夫曼算法对该文档进行压缩和解压缩操作,使得该文档占用较少的存储空间。一个较大的文件经过压缩后,产生了另外的一个较小容量的文件,我们就叫他是这些文件较大容量的(可能一个或一个以上的文件)的压缩文件。而压缩此文件的过程称为文件压缩。要使用这些经过压缩的文件,您就必须将这些经过压缩的文件还原成可以处理或执行的文件格式。目前网络上有两种常见的压缩格式:一种是 zip,另一种是 EXE。其中 zip 的压缩文件可以通过 Winzip 这套解压缩工具进行解压,而 EXE 文件内含解压缩程序,因此会比 zip略大一些。若想充分考虑到文件容量的
2、大小,其实 zip 是一个较佳的选择。而我们这个程序则可以将您选择的文件压缩成您需要的任意的格式。第 2 章 基本要求(1)假设文档内容从键盘输入;(2)设计哈夫曼算法的存储结构;(3)设计哈夫曼编码和解码算法;(4)分析时间复杂度和空间复杂度。第 3 章 概要设计3.1 数据结构的设计对于给定的文档,首先通过扫描确定文档中出现了哪些英文字母以及出现的次数,以出现的次数作为叶子结点的权值构造哈夫曼树,获得个字符的哈夫曼编码;然后在扫描一次文档将其进行哈夫曼压缩编码,将文本文档换为二进制编码输出;最后将二进制流进行解码,并与原文档进行对照,以验证算法的正确性。图 3-1 哈夫曼编码树字 符 频
3、率 编 码A 35 11B 25 00C 15 01D 15 101E 10 110图 3-2 字符编码3.2 算法的设计利用 Huffman 编码树求得最佳的编码方案。根据哈夫曼算法,建立哈夫曼树时,可以将哈夫曼树定义为一个结构型的一维数组HuffTree,保存哈夫曼树中各结点的信息,每个结点包括:权值、左孩子、右孩子、双亲,如图 6 所示。由于哈夫曼树中共有 2n-1 个结点,并且进行 n-1 次合并操作,所以该数组的长度为 2n-1。构造哈夫曼树的伪代码如下:1. 数组 huffTree 初始化,所有元素结点的双亲、左右孩子都置为-1;2. 数组 huffTree 的前 n 个元素的权值
4、置给定权值 wn;3. 进行 n-1 次合并3.1 在二叉树集合中选取两个权值最小的根结点,其下标分别为 i1, i2;3.2 将二叉树 i1、i2 合并为一棵新的二叉树 k;在哈夫曼树中,设左分支为 0,右分支为 1,从根结点出发,遍历整棵哈夫曼树,求得各个叶子结点所表示字符的哈夫曼编码。3.3 抽象数据类型的设计ADT TreeData树是由一个根结点和若干棵子树构成,树中结点具有相同数据类型及层次关系OperationInitTree前置条件:树不存在输入:无功能:初始化一棵树输出:无后置条件:构造一棵树DestroyTree前置条件:树已存在输入:无功能:销毁一棵树输出:无weight
5、 lchild rchild parent图 3-1 哈夫曼树的结点结构后置条件:释放该树占用的存储空间PreOrder前置条件:树已存在输入:无功能:前序遍历树输出:树的前序遍历序列后置条件:树保持不变PostOrder前置条件:树已存在输入:无功能:后序遍历树输出:树的后序遍历序列后置条件:树保持不变LeverOrder前置条件:树已存在输入:无功能:层序遍历树输出:树的层序遍历序列后置条件:树保持不变第 4 章 详细设计4.1 设计抽象数据类型对应的 C+类定义4.2 设计每个成员函数1)二进制转化字符函数函数名:unsigned char ctobi(char a) 操作结果:将数组的
6、前八位转成二进制形式比特位2)寻找字符的编码串函数函数名:char *code(unsigned char temp,int leaf)操作结果:寻找对应字符的编码串,并返回3)文件压缩函数函数名:void compress(char *infilename,char *outfilename)操作结果:丢文件进行压缩4)字符转换二进制函数函数名:void ctobi(unsigned char a,char code)操作结果:字符转为二进制形式存入 8 位数组5)匹配函数函数名:int strcmp1(char buf,struct node node,int n,unsigned cha
7、r struct nodeunsigned char b; /记录字符long weight; /权重int parent,lch,rch; /定义双亲,左孩子,右孩子char bits256; /存放哈夫曼编码的数组noder512,tmp; /头部一要定设置至少 512 个, 因为结点最多可达 256,所有结点数最多可达 511unsigned char ctobi(char a) /*将数组的前八位转成二进制形式比特位*/unsigned char c=0;for(int i=0;i=8) /当 buf 中字符长度大于 8 时,一直处理写入,直至小于 8temp=ctobi(buf);
8、/上面临时变量已经完成使命,可以赋新值了outfile.write(char *) /转成二进制写入clength+; /统计代码结尾偏移加 1,用于找到叶子结点位置strcpy(buf,buf+8); /字符串前移八位 /当此循环结束时,表示 buf中已经小于 8 了,没到文件末尾,读下一个,继续,否则退出 /while 此层循环退出时,表示已到末尾,再判断 buf 中是否写完,没写完,连满至少 8个字符,再写一个字节,就够了if(strlen(buf)0)strcat(buf,“0000000“);temp=ctobi(buf); /前八位转成二进制形式outfile.write(char
9、 *)clength+; /统计代码结尾偏移加 1,用于找到叶子结点位置outfile.seekp(4);outfile.write(char *) /写入文件中将记录叶子结点位置infile.close(); /*将字符编码对照表写入文件*/long bytelen; /记录编码以二进制存储时需要占多少个字节outfile.clear();outfile.seekp(clength); /将文件指针移到编码后面的第一位置,在此处记录叶子结点数outfile.write(char *) /写入叶子结点数for(i=0;i0)coden-=c%2+0;c=c/2;int strcmp1(char
10、 buf,struct node node,int n,unsigned char inoderj+1.weight)tmp=noderj;noderj=noderj+1;noderj+1=tmp;/*将编码读入内容,进行解码工作*/readlen=0;writelen=0;ofstream outfile(outfilename,ios:binary|ios:out); /打开编码后文件if(!outfile) cerr=256) /处理缓冲区,直到少于 256 位,再读满它for(i=0;i=flength) break; /如果写入达到原文件长度,退出/whileif(readlen=(
11、clength-8)/*编码长度*/|writelen=flength) break; /如果写入或者读入编码完毕,退出/退出此循环后,还有未解码完成的 buf/对 buf缓冲的善后处理while(writelenfilename;ifstream in(filename,ios:out);while(!in.eof()incontents;cout3) strcpy(select,cmdline1);strcpy(infilename,cmdline2);strcpy(outfilename,cmdline3);else if(num=1)MainMeun();coutchoice;swit
12、ch(choice)case C:coutinfilename;coutoutfilename;compress(infilename,outfilename);break;case D:coutinfilename;coutoutfilename;uncompress(infilename,outfilename);break;case H:help();break;case Q:exit(0);break;case L:show();break;return 0;5.3.2 运行结果第 6 章 总结与心得做了一个星期的程序设计终于做完了,在这次程序设计课中,真是让我获益匪浅,我突然发现写程
13、序还挺有意思的。 由于上学期的 C 语言跟这学期的数据结构都算不上真正的懂,对于书上的稍微难点的知识就是是而非的,所以我只是对老师的程序理解,我也试着去改变了一些变量,自己也尽量多的去理解老师做程序的思路。当我第一天坐在那里的时候,我就不知道该做些什么,后来我只有下来自己看了一遍书来熟悉下以前学过的知识。 通过这次的程序设计,发现一个程序设计就是算法与数据结构的结合体,自己也开始对程序产生了前所未有的兴趣,以前偷工减料的学习也不可能一下子写出一个程序出来,于是我就认真看老师写的程序,发现我们看懂了一个程序其实不难,难的是对于一个程序的思想的理解,我们要掌握一个算法,不仅仅限于读懂,主要的是要理
14、解老师的思路,学习老师的解决问题的方法。通过这次课程设计使我进一步达到理论与实际相结合,提高了自己组织数据及编写程序的能力,使我们能够根据问题要求和数据对象的特性,学会数据组织的方法,把现实世界中的实际问题在计算机内部表示出来并用软件解决问题,培养良好的程序设计技能,掌握设计程序的思路,学会用计算机语言编写程序,以实现所需处理的任务,锻炼自己的动脑能力,学会用自己的思路解决现实中的实际问题,虽然一开始也走了一些弯路不过在同学和老师的点拨下完成了该程序,最后祝愿老师身体健康,万事如意。参考文献1 王红梅.算法设计与分析.北京:清华大学出版社.2006.2 王红梅,胡明.数据结构考研辅导.北京:清华大学出版社 .2009.3 张铭,王腾蛟,赵海燕.数据结构域算法.北京:高等教育出版社 .2008.4 王红梅,胡明,王涛.数据结构(C+版).第 2 版.北京:清华大学出版社.2011.5 严蔚敏,吴为民.数据结构.北京:清华大学出版社.1997.