1、哈夫曼编码/译码 一、【实验内容】【问题描述】利用哈夫曼编码进行住处通讯可以大大提高信道利用率, 缩短住处传输时间,降低成本 ,但是 ,这要求在发送端通过一个编码系统将传输的数据预先编码, 在接收端通过一个译码系统对传来的数据进行译码( 复原),对于双向传输信息的信道,每端都一个完整的编码译码系统,试为这样的住处收发站写一个哈夫曼友的编码译码系统.【基本要求】:一个完整的系统应以下功能:(1) I. 初始化 (Initialization)。从终端读入字符集大小 n,以及 n 个字符和 n 个权值,建立哈夫曼树 ,并将它存放在文件 hfmTree 中.(2) E. 编码(Encoding)。利
2、用已建立好的哈夫曼树(如不在内存,则从文件 hfmTree 中读入),对文件 ToBeTran 中的正文进行编码,然后将结果代码存(传输 )到文件 CodeFile 中.(3) D. 译码(Decoding)。利用已建好的哈夫曼树 ,对传输到达的 CodeFile 中的数据代码进行译码, 将译码结果存入文件 TextFile 中. (4) P. 印文件代码 (Print)。将文件 CodeFile 以紧凑格式显示在终端上,每行 50 个代码。同时将此字符形式的编码文件写入文件 CodePrin 中。 (5) T. 印哈夫曼树(TreePrinting)。将已在内存中的哈夫曼树以直观的方式(树或
3、凹入表的形式) 显示在终端上,同时将此字符形式的哈夫曼树写入文件 TreePrint 中。测试数据:(1) 利用教科书例 6-2 中的数据调试程序。(2) 用下表给出的字符集和频度的计数据建立哈曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”.。字符 A B C D E F G H I J K L M频数 186 64 13 22 32 103 21 15 47 57 1 532 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 二、实验目的树型结构是一种应用极为广
4、泛的非线性数据结构,也是本课程的重点内容, 哈夫曼树 (最优二叉树)是树型结构的典型应用 ,本次实验突出了数据结构加操作的程序设计观点,希望能根据树型结构的非线性特点, 熟悉各种存储结构的特性,达到如何应用树型结构的非线性特点, 熟悉各种存储结构的特性, 达到如何应用树型结构解决具体问题的目的.三、实验文档:哈夫曼编码/ 译码一、 需求分析1、 利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(既可以双向传输信息的信道),每端都需要一个完整的编/译码系统。
5、本次设计就是为这样的信息收发站写的一个哈夫曼的编/译码器。本实验要求:2、本演示程序中,用户可以输入键盘中的任意字符,长度为任意长,字符输入顺序不限,且允许出现重码3、演示程序以用户与计算机的对话方式执行,即在计算机终端上显示“提示信息”之后,由用户在键盘上输入演示程序中规定的运算命令,相应的输入数据(可虑去输入中的非法字符)和运算结果显示在其后。4、本演示程序中,当用户选择的功能错误时,系统会输出相应的提示。5、在本系统中,用户可以对任意长的字符串可进行编码/译码。6、程序执行的命令包括:1) 初始化 (I) 2) 编码(E) 3) 译码(D) 4) 印代码文件(P) 5) 印哈夫曼树(T)
6、 6) 退出(Q)、测试数据:()利用教科书例 6-2 中的数据调试程序。()用下表给出的字符集和频度的计数据建立哈曼树,并实现以下报文的编码和译码:“THIS PROGRAM IS MY FAVORITE”.。字符 A B C D E F G H I J K L M频数 186 64 13 22 32 103 21 15 47 57 15 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. 抽象数据类型定义为:ADT
7、 HuffmanTree数据对象:D=ai| aiCharSet,i=1,2,n, n0数据关系:R= ai-1, aiD, ai-1#include#includeusing namespace std;struct HuffmanNode /定义哈夫曼树各结点int weight; /存放结点的权值,假设只考虑处理权值为整数的情况int parent; /记录结点父亲位置,-1 表示为根结点,否则表示为非根结点int lchild,rchild; /分别存放该结点的左、右孩子的所在单元的编号;class HuffmanTree /建立哈夫曼树类private:HuffmanNode *No
8、de; /哈夫曼树中结点的存储结构char *Info; /用来保存各字符信息int LeafNum; /树中的叶子结点总数public:HuffmanTree(); /构造函数HuffmanTree(); /析构函数void Initialization(int WeightNum); /初始化函数:根据 WeightNum 个权值建立一棵哈夫曼树void Encoder(); /编码函数:利用构造好的哈夫曼树对字符进行编码void Decoder(); /译码函数:对二进制串进行译码void Print(); /印文件函数:把已保存好的编码文件显示在屏幕void TreePrinting(
9、); /印哈夫曼树函数:将已在内存中的哈夫曼树以直观的方式显示在终端上;/ 程序名:HuffmanTree.cpp/ 程序功能:实现哈夫曼树类的源文件(并用其来实现编/译码)/ 作者:刘伟高/ 日期:2006.11.27/ 版本:1.0#include“HuffmanTree.h“#includeusing namespace std;/ 构造函数/ 函数功能:将结点指针初始化为 NULL/ 函数参数:无/ 参数返回值:无HuffmanTree:HuffmanTree()Node=NULL; /将树结点初始化为空 Info=NULL; /将字符数组初始化为空LeafNum=0; /将叶子数初始
10、化为 0/ 析构函数/ 函数功能:将所有结点的空间释放/ 函数参数:无/ 参数返回值:无HuffmanTree:HuffmanTree()delete Node; /释放结点空间delete Info; /释放字符存储空间/ 初始化函数/ 函数功能:从终端读入字符集大小 n,以及 n 个字符和 n 个权值,/ 建立哈夫曼树 ,并将它存放在文件 hfmTree 中./ 函数参数:int WeightNum 表示代码个数/ 参数返回值:无 void HuffmanTree:Initialization(int WeightNum) /初始化int i,j,pos1,pos2,max1,max2;
11、/Node=new HuffmanNode2*WeightNum-1; /WeightNum权值对应的哈夫曼树中的结点总数为 2*WeightNum-1 个Info=new char2*WeightNum-1;for(i=0;iNodei.weight; /输入权值Nodei.parent=-1; /为根结点Nodei.lchild=-1; /无左孩子Nodei.rchild=-1; /无右孩子for(i=WeightNum;ich;if(ch=y|ch=Y)ofstream fop; /以二进制方式打开 hfmTree.dat 文件,并当重新运行时覆盖原文件fop.open(“hfmTree
12、.dat“,ios:out|ios:binary|ios:trunc);if(fop.fail() /文件打开失败coutChoose;if(Choose=1) /读取文件 ToBeTran.txtifstream fip1(“ToBeTran.txt“);if(fip1.fail() /文件不存在coutLeafNum-1;i-) /输出哈夫曼树cout=0;i-)cout#include/ 主函数/参数返回值:无int main()coutChoose;switch(Choose)case I:case i:coutweight;huftree.Initialization(weight)
13、; /初始化哈夫曼树break;case E:case e:huftree.Encoder();break;case D:case d:huftree.Decoder();break;case P:case p:huftree.Print();break;case T:case t:huftree.TreePrinting();break;case Q:case q:cout“n *感谢使用本系统!*nn“;system(“pause”); /暂停运行return 0;cout“(1) 初始化 (I) (2) 编码(E) (3) 译码(D)n“;cout“(4) 印代码文件 (P) (5) 印
14、哈夫曼树(T) (6) 退出(Q)n“;四、调试分析1、由于二维指针和 string 类,还有文件操作的推敲不足,使程序调试时费时不少。还有对单个空格字符的输入,也花了一些时间,不过最终能实现单个空格的输入,还是值得的。2、本程序有些代码重复出现,从而减少了空间的利用率和增加了程序代码的杂乱性,特别是文件操作方面,如果可能的话,可以把文件读入、读出分别写成一个函数(就是把文件名作为参数),然后就可以直接调用了。3、本程序模块划分比较合理,且利用指针和 string 类对象实现字符串的操作,操作方便。4、算法的时空分析在此程序中,存储字符串都用了指针,先动态申请空间,然后再存,这样就有效的利用了空间,不过为了实现任意长字符串的输入,引入了 string 类,先定义 string 对象,再输入。最后转存到字符指针里,这样就浪费了一些空间。而对于哈夫曼树算法本身,由于这里只是一个静态的,所以当进行网络传输时,可能会显得效率比较低。5、本实验采用数据抽象的程序设计方法,将程序分为 3 个模块,使得设计时思路清晰,实现时调试可以顺利完成,各模块具有较好的可重用性,确实得到了一次良好的程序设计训练。五、用户手册1、本程序的运行环境为 DOS 操作系统2、进入演示程序后即显示文本方式的用户界面3、进入界面后,就会提示输入字符串的输入形式,结束符为“ 回车符” 。六、测试结果