huffman编解码问题——讲解

上传人:F****n 文档编号:97826199 上传时间:2019-09-06 格式:DOCX 页数:9 大小:66.51KB
返回 下载 相关 举报
huffman编解码问题——讲解_第1页
第1页 / 共9页
huffman编解码问题——讲解_第2页
第2页 / 共9页
huffman编解码问题——讲解_第3页
第3页 / 共9页
huffman编解码问题——讲解_第4页
第4页 / 共9页
huffman编解码问题——讲解_第5页
第5页 / 共9页
点击查看更多>>
资源描述

《huffman编解码问题——讲解》由会员分享,可在线阅读,更多相关《huffman编解码问题——讲解(9页珍藏版)》请在金锄头文库上搜索。

1、在能力与知识结构方面,要求学生应具有扎实的专业和日语语言基础,熟练掌握日语听、说、读、写、译的基本技能;了解日本社会及日本文化等方面的基本知识,熟悉日本国情,具有一定的日本人文知识及运用这些知识与日本人进行交流的能力。2.5 Huffman编码问题实验四题目2:利用二叉树结构实现哈夫曼编/解码器。基本要求:1、初始化(lnit):能够对输入的任意长度的字符串s进行统计,统计每个字符的频度, 并建立哈夫曼树2、建立编码表(CreateTable):利用己经建好的哈夫曼树进行编码,并将每个字符的 编码输出。3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输出。4、

2、译码(Decoding):利用己经建好的哈夫曼树对编码后的字符串进行译码,并输出 译码结果。5、打印(Print):以直观的方式打印哈夫曼树(选作)6、计算输入的字符串编码前和编码后的长度,并进行分析,讨论赫夫曼编码的压 缩效果。7、可采用二进制编码方式(选作)实验讲解:Huffman编解码的实验按照模块化分,可以划分成如下部分:a) 统计输入的字符串中字符频率b) 创建Huffman树c) 打印Huffman树d) 创建Huffman编码表e) 对输入的字符串进行编码并输出编码结果f) 对编码结果进行解码,并输出解码后的字符串g) 最后编写测试函数,测试上述步骤的正确性。根据模块化分,设计H

3、uffman的存储结构如下:1) Huffman树的结点结构 struct HNode int weight;/结点权值int parent;/双亲指针int LChild;/左孩子指针int RChild ;/右孩子指针;20datacode0Z1001C1012B113A052)编码表结点结构(如右图2-6所示)11struct HCode char data; char code100;图2-6 Huffman树编码结构3) Huffman类结构class Huffmanprivate:HNode* HTree; HCode* HCodeTable; char str1024; char

4、 leaf256; int a256; public:/Huffman 树 /Huffman 编码表/输入的原始字符串 /叶子节点对应的字符 /记录每个出现字符的个数int n;/叶子节点数void init();/初始化void CreateHTree();/创建 huffman 树voidSelectMin(int &x, int &y, int s, int e );void CreateCodeTable();/创建编码表void Encode(char *d);/编码void Decode(char *s, char *d);/解码void print(int i, int m);/

5、打印 Huffman 树Huffman();根据实验要求,分步骤实现如下:步骤1:统计输入的字符串中字符频率Huffman编码的第一步需要使用字符出现的频率作为输入,本实验使用从键盘输入的方 式进行,需要的解决得问题有2个:一是输入的字符串中间有空格如何处理?二是如何使统 计效率更高?例如:char str1024; cinstr;上述代码运行后输入字符串,但cmstr遇到空格就停止本次读取,所以我们需要使用 其它的方法来进行输入,即需要使用cm.get()函数进行字符串读取。get()方法每调用一次, 读取一个字符,该字符的ASCII码作为返回值返回,换行回车等控制字符也当作普通字符进行读取

6、,因此需要指定结束读取的标志字符,才能停止get()函数的循环调用。 本实验中可以将字符读取和统计结合在一起进行。示例代码如下:/记录每一个字符出现的次数/统计字符出现的次数 /记录原始字符串 /读取下一个字符 int nNum256= 0; int ch = cin.get(); int i=0; while(ch!=V) & (ch!=n) nNumch+; stri+ = ch; ch = cin.get(); stri=,0其中,整型数组变量nNum用来记录每一个字符出现的次数(若该字符未出现,则对应 的nNumch的值为0),可以把读取的字符ch的ASCII码当成,当ch出现时,nN

7、umch自动加一。当然,数组nNum中的等于零的字符会有很多,不方便后续hufman树的创建,因此可以进行过滤,仅留下出现次数大于零的字符。因此,完整的初始化代码如下: void Huffman:init()n = 0;for ( i=0;i0)/若nNumi=0说明该字符未出现leafn = (char)i; an = nNumi;n+;其中,数组leaf存储出现次数大于零的字符,相应的数组a存储该字符出现的次数,n 为字符数,作为步骤2创建Huffman树的输入。字符数组str存储用户输入的字符串,作为 步骤5编码的输入。当然,也可以使用其它方法进行字符的统计,请读者自行思考。步骤2:创建

8、Huffman树该步骤在教材5.4.2小节中进行了详细的讲解和实现,其中有一个选择权值之中最小的两个 权值的函数,即函数SelectMin(int &x, int &y, int s, int e );其中x为最小权值,y为次小权值,s为权值范围的起始下标,e为结束下标。该函数如何实现呢? 分析:从所有未使用过的权值表中选择两个最小的权值,可以有多种方法,比如一次选择一 个最小的,选择2遍;或者进行迭代,一次选择出两个。显然,后者的时间效率较高,因此 我们采用后者进行实现。迭代选择两个最小值得基本思想是:1、从权值表HTrees.e中选取第一个未使用结点下标为x,并设y=x;2、从剩下的未使用

9、的权值中依次遍历若当前结点i的权值结点x的权值,则迭代,即y=x; x = i;否则:若此时y=x (即y还未赋值),则y=i;若此时当前结点i的权值y结点的权值,则y=i;具体实现如下:void Huffman:SelectMin(int &x, int &y, int s, int e )int i;for ( i=s; i=e;i+)if (HTreei.parent = -1)x =y= i; break;/找出第一个有效权值x,并令y=xfor ( ; ie;i+)if (HTreei.parent = -1)/该权值未使用过if ( HTreei.weight HTree x.we

10、ight)y = x; x = i;/迭代,依次找出前两个最小值else if (x=y) | (HTreei.weight HTree y.weight)y = i;/找出第2个有效权值y特别说明,本例中叶子节点数n作为成员变量,因此,huffman类的成员函数的参数中 不必在添加int n这个参数,直接使用n即可。步骤3:打印Huffman树Huffman树的直观表示方式由多种,我们常见的树状结构如图所示是其中的一种,此外 还有如图a所示的嵌套集合表示法,如图b所示的广义表表示法和图c所示的凹入表示法。A图-7树型表示法图-8其他表示法树型表示法当结点很多的时候,不容易打印的非常合适,所以

11、我们可以选择使用凹入表 的方式打印任意形状的Huffman树。根结点空一格直接打印,第2层结点空2格打印,第3 层结点空3格的打印,以此类推,每个节点占用独立的一行。由于只有叶子结点是有对应字 符的,所以其他结点可以打印该结点的权值。因此,我们可以尝试使用二叉树前序遍历的方 式来进行直观的打印。示例代码如下:#define N 10/定义树的最大深度void Huffman:print(int i, int m)if (HTreei.LChild = -1)coutsetfill( )setw(m+1)leafisetfill(-)setw(N-m)n;elsecoutsetfill( )se

12、tw(m+1)HTreei.weightsetfill(-)setw(N-m)n; print(HTreei .LChild,m+1); print(HTreei .RChild,m+1);其中,参数i表示Huffman树的下标为i的结点,m表示该结点的层次。该函数是递归 函数,所以在main()函数中第一次调用该函数时,实参为i=2*n-2, m=1;步骤4:创建编码表该步骤请参考教材5.4.2小节中的讲解和实现即可。 步骤5:编码编码表生成后,进行编码相对容易,实验要求只要能够显示出来编码后的字符串即可,也就 是说,若A的编码为0,B的编码为10,则字符串AAB的编码显示为0010即可。由

13、于初始化函数中己经记录了输入的字符串str,因此直接使用该变量作为输入即可。 void Huffman:Encode(char *d)char *s = str; while(*s!=0)for (int i=0;in;i+)if (*s = HCodeTablei.data )strcat(d, HCodeTablei.code);/d 为编码后的字符串break;s+;上述代码用于本实验的编码显示和验证是没问题的,但并没有实现真正的压缩效果,这时因 为代码的实现。比如若A的编码为100,实际压缩中使用3个bit代替字符A,本例中使 用了 3个字符“100”来编码,因此没有真正的压缩效果。如

14、果希望能够按照bit的方式进 行编码,需要使用位运算符进行bit的操作,将编码按照bit的方式写入文件。请同学们自行思考,如何采用bit的方式使用Huffman编码压缩文件。步骤6:解码该步骤请参考教材5.4.2小节中的讲解和实现即可。步骤7:测试根据测试数据,编写如下的测试man()函数进行测试: void main()Huffman HFCode;cout请输入要编码的字符串:;HFCode.init();cout创建 Huffman 树:endl;HFCode.CreateHTree();HFCode.print(2*HFCode.n-2,1);cout”创建 Huffman 编码表:endl; HFCode.CreateCodeTable();char d1024=0;HFCode.Encode(d);cout编码结果:dendl;char s1024=0;HFCode.Decode(d,s); c

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 教学/培训

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号