1、问题描述:利用哈夫曼编码进行信息通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是这要求在发送端通过一个编码系统对待传数据预先编码;在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编译码系统。具体要求:1)初始化:键盘输入字符集大小n及n个字符和m个权值,建立哈夫曼树,并将它存于文件hfmtree中。 2)编码:利用建好的哈夫曼树,对文件tobetrans中的正文进行编码,然后将结果存入文件codefile中。3)解码:利用建好的哈夫曼树将文件codefile中的代码进行译码,结
2、果存入文件textfile中。4)打印代码文件:将文件codefile以紧凑格式显示在终端上,每行50个代码。同时将此字符形式的编码文件写入文件codeprint中。5)打印哈夫曼树:将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件treeprint中。6)设字符集及频度如下表:字符空格ABCDEFGHIJKLM频度18664232232103211547571520NOPQRSTUVWXYZ561925051553010113 系统设计(1)设计思路及方案本课题是用最优二叉树即哈夫曼树来实现哈夫曼编码译码器的功能。假设每种字符在电文中出现的
3、次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为(W1*L1)+(W2*L2)+(Wi*Li)。若将此对应到二叉树上,Wi为叶结点,Li为根结点到叶结点的路径长度。那么,(W1*L1)+(W2*L2)+(Wi*Li)恰好为二叉树上带权路径长度。因此,设计电文总长最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一棵哈夫曼树,此构造过程称为哈夫曼编码。该系统将实现以下几大功能:从硬盘读取字符串,建立哈夫曼树,输出哈夫曼树的存储结构的初态和终态,输出各种字符出现的次数以及哈夫曼编码的译码等。(2)模块的设计及介绍从硬盘读取字符串fileopen(参数) 实现命令; 打印输出;
4、建立HuffmanTree通过三个函数来实现:void select(参数) 初始化; for 接受命令; 处理命令;说明:在ht1.k中选择parent为0且权值最小的两个根结点的算法int jsq(参数) 统计字符串中各种字母的个数以及字符的种类void ChuffmanTree() 输出字符统计情况;构造哈夫曼树输出哈夫曼树的存储结构的初态和终态分别调用print1()和print2()来实现void print1(参数) 输出初态;输出哈夫曼树的初态void print2(参数) 输出终态;输出哈夫曼树的终态哈夫曼编码和译码void HuffmanEncoding(参数) 定义变量;
5、哈夫曼编码char*decode(参数)while接受命令;处理命令;哈夫曼译码(3)主要模块程序流程图下面介绍三个主要的程序模块流程图: 主函数流程图: 图3.1流程图注释:该图比较简单,主要是调用各个函数模块,首先代开已经存在的文件,然后统计总的字符数以及出现的各个字符和频率。然后才开始建立哈夫曼树,接着在哈夫曼树的基础上对其进行编码,编码之后才是译码。最后输出结束。构造哈夫曼树: 图3.2该图是表示构造哈夫曼树的过程。首先输入num个叶结点的权值,当i=num是循环结束。然后进行哈夫曼树的构建,当i=2*num-1是循环结束。最后输出所得到的字符统计情况。哈夫曼编码: 图3.3 流程图解
6、释:该流程图表四哈夫曼编码情况。首先初始化,Cd-start=0,start=num。然后进行编码,使用了一个三目运算符。cd-start=(Tp.lchild=c) ? 0 :1,即当cd-start=Tp.lchild= =c时,cd-start=0;当cd-start=Tp.lchild!= =c时,cd-start=1。这个编码循环一直到i=num时结束。4 系统实现各模块关键代码及算法的解释:(1)主调函数 代码解释:这是main函数里的各个函数调用情况。fileopen(string); /从硬盘中读取文件 num=jsq(string,cnt,str); /统计字符种类及各类字符
7、出现的频率 DhuffmanTree(HT,cnt,str); printf(HuffmanTree的初态:n); print1(HT); /输出哈夫曼树的初态 ChuffmanTree(HT,HC,cnt,str);/建立哈夫曼树 HuffmanEncoding(HT,HC); /生成哈夫曼编码HuffmanTree的终态: print2(HT); /输出哈夫曼树的终态 s=decode(HC); /读编码文件译码译码后的字符串:%sn,s); /输出译码后的字符串(2)建立HuffmanTree 代码解释:该函数为在ht1.k中选择parent为0且权值最小的两个根结点的算法,其序号为s1
8、和s2。void select(HuffmanTree T,int k,int &s1,int &s2) int i,j;int min1=101; for(i=1;i=k;i+) if(Ti.weightmin1 &Ti.parent=0) j=i;min1=Ti.weight; s1=j;min1=32767; for (i=1; if(Ti.weightA*pZ) k=*p-64; tempk+; /统计各种字符的个数 for(i=1,j=0;+i) if(tempi!=0 ) j+; strj=i+64; /送对应的字母到数组中 cntj=tempi; /存入对应字母的权值 retur
9、n j; /j是输入字母总数下面函数用来构造哈夫曼树HT。首先初始化哈夫曼树,然后输入前面统计的各结点的权值,用for循环来构造哈夫曼树。void ChuffmanTree(HuffmanTree HT,HuffmanCode HC,int cnt,char str) int i,s1,s2;for(i=1;=2*num-1;i+)/初始化HT,2*num-1是指哈夫曼/所有的结点数目 HTi.lchild=0;HTi.rchild=0; HTi.parent=0;HTi.weight=0; =num;i+) /输入num个叶结点的权值 HTi.weight=cnti; for(i=num+1; select(HT,i-1,s1,s2); HTs1.parent=i;HTs2.parent=i; HTi.lchild=s1; HTi.rchild=s2; HTi.weight=HTs1.weight+HTs2.weight;/在ht1.k中选择parent为0且权值最小/
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1