1、课程设计任务书20112012 学年第一学期专业: 通信工程 学号: 080110005 姓名: 刘胜英 课程设计名称: 信息论与编码课程设计 设计题目: M 进制哈夫曼编码的分析与实现 完成期限:自 2011 年 12 月 19 日至 2011 年 12 月 25 日共 1 周一设计目的1、深刻理解信源编码的基本思想与目的;2、理解哈夫曼编码方法的基本过程与特点;3、提高综合运用所学理论知识独立分析和解决问题的能力;4、使用 MATLAB 或其他语言进行编程。二设计内容假设已知一个信源的各符号概率,编写适当函数,对其进行哈夫曼编码,得出 M 进制码字,平均码长和编码效率,总结此编码方法的特点
2、和应用。三设计要求1、编写的函数要有通用性;2、信源可以自由选择,符号信源与图像信源均可。四设计条件计算机、MATLAB 或其他语言环境五参考资料1曹雪虹,张宗橙.信息论与编码.北京:清华大学出版社,2007.2王慧琴.数字图像处理 .北京:北京邮电大学出版社,2007.指导教师(签字): 教研室主任(签字): 批准日期: 年 月 日摘 要哈夫曼编码(Huffman Coding)是一种编码方式,也是可变字长编码 (VLC)的一种。这种方法完全依据字符出现的概率来构造异字头的平均长度最短的码字,有时称之为最佳编码,一般就叫作哈夫曼编码。对于 M 进制哈弗曼编码,为了提高编码效率,就要使长码的符
3、号数量尽量少、概率尽量小,所以应使合并的信源符号位于缩减信源序列尽可能高的位置上,以减少再次合并的次数,充分利用短码。本文将采用三进制哈夫曼编码作为例子来诠释 M 进制哈夫曼编码。在三进制哈夫曼编码中,得出码字、平均码长和编码效率,构造哈夫曼树,沿着根节点到叶节点从左到右依次为 0、1、2,保证平均码长最小。在本文中采用 Visual C+6.0 进行编程,此程序中具有输入字符集大小和权值大小,构造哈夫曼树,并对用户输入的字符串进行编码等功能。关键词:哈弗曼编码;信源;哈夫曼树;Visual C+6.0;目 录1 课题描述 .12 设计原理 .13 设计过程 23.1 软件介绍 .23.1.1
4、 Visual C+ 6.0 简介 .23.1.2 主要部分 .33.2 设计内容 .44 编码程序分析及其结果 .6总 结 14参考文献 15课程设计说明书(论文)第 1 页 共 15 页1 课题描述在这个信息量爆炸的时代,凡是能载荷一定信息量,且码字的平均长度最短,可分离的变长码的码字集合称为最佳变长码。为此,必须将概率大的信息符号编以短的码字,概率小的符号编以长的码字,使得平均码字最短。能获得最佳码的编码方法主要有:香农(Shannon) 、费诺(Fano) 、哈夫曼(Huffman)编码等。哈夫曼(Huffman)编码是一种常用的压缩编码方法,是 Huffman 于 1952 年为压缩
5、文本文件建立的。它的基本原理是频繁使用的数据用较短的代码代替,较少使用的数据用较长的代码代替,每个数据的代码各不相同。哈 夫 曼 压 缩 是 个 无 损 的 压 缩 算 法 , 一 般 用 来 压 缩 文 本 和 程 序 文 件 。 哈 夫曼 压 缩 属 于 可 变 代 码 长 度 算 法 一 族 。 意 思 是 个 体 符 号 用 一 个 特 定 长 度 的 位 序列 替 代 。 因 此 , 在 文 件 中 出 现 频 率 高 的 符 号 , 使 用 短 的 位 序 列 , 而 那 些 很 少出 现 的 符 号 , 则 用 较 长 的 位 序 列 。哈 夫 曼 编 码 是 哈 夫 曼 树 的
6、 一 个 应 用 , 是 一 种 最 优 的 前 缀 技 术 , 然 而 其存 在 的 不 足 却 制 约 了 它 的 直 接 应 用 。 首 先 , 其 解 码 时 间 为 O(lavg), 其 中lavg 为 码 字 的 平 均 长 度 ; 其 次 , 更 为 重 要 的 是 , 解 码 器 需 要 知 道 哈 夫 曼 编 码树 的 结 构 , 因 而 编 码 器 必 须 为 解 码 器 保 存 或 传 输 哈 夫 曼 编 码 树 。 对 于 小 量 数据 的 压 缩 而 言 , 这 是 很 大 的 开 销 。 因 而 , 应 用 哈 夫 曼 编 码 的 关 键 是 如 何 降 低哈 夫
7、曼 编 码 树 的 存 储 空 间 。 目 前 流 行 的 很 多 压 缩 方 法 都 是 用 了 该 技 术 , 如GZIB、 ZLIB、 PNC 等 。2 设计原理对于多进制哈夫曼编码,为了提高编码效率,就要是长码的符号数量尽量少、概率尽量小,所以信源符号数量最好满足 n=(m-1)*k+r,其中 m 为进制数,k 为缩减的次数。设计步骤如下:课程设计说明书(论文)第 2 页 共 15 页1将信源符号按概率从大到小的顺序排列,令p(x1) p(x2) p(xn)2给两个概率最小的信源符号 p(xn-1)和 p(xn)各分配一个码位“0”和“1”,将这两个信源符号合并成一个新符号,并用这两个
8、最小的概率之和作为新符号的概率,或者在新添加一个信源符号,令其概率为 0,则个分配一个码位“0”、 “1”和“2”,将其合并,结果得到一个只包含(n1)个信源符号的新信源。称为信源的第一次缩减信源,用 S1 表示。3将缩减信源 S1 的符号仍按概率从大到小顺序排列,此后每次合并 3 个信源符号,得到只含(n3) 个符号的缩减信源 S2。4重复上述步骤,直至最后,此时所剩符号的概率之和必为 1。然后从最后一级缩减信源开始,依编码路径向前返回,就得到各信源符号所对应的码字。3 设计过程3.1 软件介绍3.1.1 Visual C+ 6.0 简介Visual C+ 6.0,简称 VC 或者 VC6.
9、0,是微软推出的一款 C+编译器,将“高级语言”翻译为“机器语言(低级语言) ”的程序。 Visual C+是一个功能强大的可视化软件开发工具。自 1993 年 Microsoft 公司推出 Visual C+1.0 后,随着其新版本的不断问世,Visual C+已成为专业程序员进行软件开发的首选工具。Visual C+6.0 由 Microsoft 开发, 它不仅是一个 C+ 编译器,而且是一个基于Windows 操作系统的可视化集成开发环境(integrated development environment,IDE) 。Visual C+6.0 由许多组件组成,包括编辑器、调试器以及程序
10、向导 AppWizard、类向导 Class Wizard 等开发工具。 这些组件通过一个名为 Developer Studio 的组件集成为和谐的开发环境。 Microsoft 的主力软件产品。Visual C+是一个功能强大的可视化软件开发工具。Visual C+6.0 以拥有“ 语法高亮” ,自动编译功能以及高级除错功能而著称。比如,它允许用户进行远程调试,单步执行等。还有允许用户在调试期间重新课程设计说明书(论文)第 3 页 共 15 页编译被修改的代码,而不必重新启动正在调试的程序。其编译及创建预编译头文件(stdafx.h)、最小重建功能及累加连结(link)著称。这些特征明显缩短
11、程序编辑、编译及连结的时间花费,在大型软件计划上尤其显著。3.1.2 主要部分1Developer Studio图 1 Developer Studio 环境这是一个集成开发环境,我们日常工作的 99%都是在它上面完成的,再加上它的标题赫然写着“Microsoft Visual C+”,所以很多人理所当然的认为,那就是 Visual C+了。其实不然,虽然 Developer Studio 提供了一个很好的编辑器和很多 Wizard,但实际上它没有任何编译和链接程序的功能,真正完成这些工作的幕后英雄后面会介绍。我们也知道,Developer Studio 并不是专门用于 VC的,它也同样用于
12、VB,VJ,VID 等 Visual Studio 家族的其他同胞兄弟。所以不要把 Developer Studio 当成 Visual C+, 它充其量只是 Visual C+的一个壳子而已。这一点请切记! 2MFC从理论上来讲,MFC 也不是专用于 Visual C+,Borland C+,C+Builder和 Symantec C+同样可以处理 MFC。同时,用 Visual C+编写代码也并不意味着一定要用 MFC,只要愿意,用 Visual C+来编写 SDK 程序,或者使用STL,ATL,一样没有限制。不过,Visual C+本来就是为 MFC 打造的,Visual C+中的许多特
13、征和语言扩展也是为 MFC 而设计的,所以用 Visual C+而不用MFC 就等于抛弃了 Visual C+中很大的一部分功能。但是,Visual C+也不等于 MFC。 3Platform SDK这才是 Visual C+和整个 Visual Studio 的精华和灵魂,虽然我们很少能直课程设计说明书(论文)第 4 页 共 15 页接接触到它。大致说来,Platform SDK 是以 Microsoft C/C+编译器为核心(不是 Visual C+,看清楚了) ,配合 MASM,辅以其他一些工具和文档资料。上面说到 Developer Studio 没有编译程序的功能,那么这项工作是由谁
14、来完成的呢?是 CL,是 NMAKE,和其他许许多多命令行程序,这些我们看不到的程序才是构成 Visual Studio 的基石。3.2 设计内容例:对如下单符号离散无记忆信源编三进制哈夫曼码。这里:m=3,n=8令 k=3,m +k(m1)=9,则 s=9n=9 8=1所以第一次取 ms=2 个符号进行编码。由计算可得:平均码长为:(3.1)信息率为:(3.2)编码效率为:(3.3)可见:哈夫曼的编码效率相当高,对编码器的要求也简单得多。编码过程如下:12345678,()0.48.010.54XxxxxP 51()0.41(.80.706)2(.504)31.69(/)iiKpxk比 特
15、符 号221.69log3l.8(/)RL比 特 符 号().59.2%68HXR课程设计说明书(论文)第 5 页 共 15 页表 1 哈夫曼编码缩减信源信源符号 概率 1s23s4码字 码长1x0.4 0 120.18 10 23x0.111 240.1 12 25x0.07 21 260.06 22 27x0.05 200 380.040.09010.2201210 1.012201 300121210202课程设计说明书(论文)第 6 页 共 15 页图 2 哈夫曼树4 编码程序及其分析/*哈夫曼编码*#include #include #include #include #includ
16、e #include /为了使用 vector 容器using namespace std; /vector 属于 std 命名域,因此使用全局命名域方式struct Huffman_InformationSource /信源类型char InformationSign10; /信源符号double Probability; /概率char Code10; /编码结果int CodeLength; /码长;struct HuffNode /哈夫曼树的节点类型char InformationSign10;double Probability;HuffNode *LeftSubtree,*midd
17、leSubtree,*RightSubtree,*Next;char Code10;int CodeLength;class CHuffman_3 /三进制哈夫曼编码public:CHuffman_3() /初始化课程设计说明书(论文)第 7 页 共 15 页ISNumber=0;AvageCodeLength=0.0;InformationRate=0.0;CodeEfficiency=0.0;CHuffman_3()DestroyBTree(HuffTree);void Huffman_Input(); /输入信息void Huffman_Sort(); /排序void Huffman_T
18、ree(); /构造哈夫曼树void Huffman_Coding(); /生成哈夫曼编码void Huffman_CodeAnalyzing(); /结果分析void Huffman_Display(); /显示结果信息void DestroyBTree(HuffNode *TreePointer); /释放资源private:vectorISarray; /声明 ISarray 数组,初始时为空int ISNumber; /符号个数double AvageCodeLength; /平均码长double InformationRate; /信息率double CodeEfficiency;
19、/编码效率HuffNode * HuffTree; /哈夫曼树private:void Huffman_Code(HuffNode *TreePointer);/输入信源信息void CHuffman_3:Huffman_Input()Huffman_InformationSource temp1=“A“,0.40,“,0;ISarray.push_back(temp1);Huffman_InformationSource temp2=“B“,0.18,“,0;ISarray.push_back(temp2);Huffman_InformationSource temp3=“C“,0.10,“
20、,0;ISarray.push_back(temp3);Huffman_InformationSource temp4=“D“,0.10,“,0;ISarray.push_back(temp4);Huffman_InformationSource temp5=“E“,0.07,“,0;ISarray.push_back(temp5);Huffman_InformationSource temp6=“F“,0.06,“,0;ISarray.push_back(temp6);课程设计说明书(论文)第 8 页 共 15 页Huffman_InformationSource temp7=“G“,0.0
21、5,“,0;ISarray.push_back(temp7);Huffman_InformationSource temp8=“H“,0.04,“,0;ISarray.push_back(temp8);ISNumber=ISarray.size();/按概率“从大到小” 排序:void CHuffman_3:Huffman_Sort()Huffman_InformationSource temp;int i,j;for(i=0;iInformationSign,ISarray0.InformationSign);ptr1-Probability=ISarray0.Probability;str
22、cpy(ptr1-Code,ISarray0.Code); ptr1-LeftSubtree=NULL;ptr1-middleSubtree =NULL;ptr1-RightSubtree=NULL;ptr1-Next=NULL; HuffTree=ptr1; /赋给数据成员 HuffTreefor(i=1;iInformationSign,ISarrayi.InformationSign);ptr2-Probability=ISarrayi.Probability;strcpy(ptr2-Code,ISarrayi.Code); 课程设计说明书(论文)第 9 页 共 15 页ptr2-Lef
23、tSubtree=NULL;ptr2-middleSubtree =NULL;ptr2-RightSubtree=NULL;ptr2-Next=ptr1;ptr1=ptr2;/结果:链表的表头为数组的最小元素。HuffTree=ptr1; /使 HuffTree 指向链表头/(2):基于链表,构造哈夫曼树int k; /树的层次int s; /需要添加的无用符号的数目。k=ceil(double)(ISNumber-3)/(3-1); /“3”:表示三进制/ceil 函数:向上取整;/floor 函数:向下取整s=3+k*(3-1)-ISNumber;if(s=1) /第一次取 m-s=3-1
24、=2 个符号/合并概率最小的二个节点 ptr1、ptr2,生成一个新节点 ptr4:ptr2=ptr1-Next;ptr4=new HuffNode;strcpy(ptr4-InformationSign,“*“); /新节点的符号为“*”ptr4-Probability=ptr1-Probability+ptr2-Probability; /新节点的概率为二者之和strcpy(ptr4-Code,“); ptr4-LeftSubtree =NULL;ptr4-middleSubtree=ptr1; /最小的节点 ptr1 成为 ptr4 的“中”子树,将来赋予码元 “1”ptr4-Right
25、Subtree=ptr2; /次小的节点 ptr2 成为 ptr4 的“右” 子树,将来赋予码元“0”HuffTree=ptr2-Next; /指向下一个节点/重新排序:temp1=HuffTree;while(temp1temp1=temp1-Next;ptr4-Next=temp1; /插在当前节点 temp1 之前if(temp1=HuffTree)HuffTree=ptr4;else temp2-Next=ptr4; /插在 temp2 节点之后ptr1=HuffTree;课程设计说明书(论文)第 10 页 共 15 页while(ptr1-Next)/合并概率最小的三个节点 ptr1
26、、ptr2,生成一个新节点 ptr4:ptr2=ptr1-Next;ptr3=ptr2-Next;ptr4=new HuffNode;strcpy(ptr4-InformationSign,“*“); /新节点的符号为“*”ptr4-Probability=ptr1-Probability+ptr2-Probability+ptr3-Probability; /新节点的概率为三者之和strcpy(ptr4-Code,“); ptr4-LeftSubtree=ptr1; /最小的节点 ptr1 成为 ptr4 的“左” 子树,将来赋予码元“2”ptr4-middleSubtree=ptr2/次小
27、的节点 ptr2 成为 ptr4 的“中” 子树,将来赋予 “1”ptr4-RightSubtree=ptr3;/次次小的节点 ptr3 成为 ptr4 的“右” 子树,将来赋予 “0”HuffTree=ptr3-Next;temp1=HuffTree;while(temp1temp1=temp1-Next;ptr4-Next=temp1; /插在当前节点 temp1 之前if(temp1=HuffTree)HuffTree=ptr4;else temp2-Next=ptr4; /插在 temp2 节点之后ptr1=HuffTree;/释放:ptr1=NULL;ptr2=NULL;ptr3=N
28、ULL;ptr4=NULL;temp1=NULL;temp2=NULL;/设置根节点:strcpy(HuffTree-Code,“);HuffTree-CodeLength=0;课程设计说明书(论文)第 11 页 共 15 页/生成哈夫曼码:void CHuffman_3:Huffman_Code(HuffNode *TreePointer)if (TreePointer = NULL)return;char tempstr10=“;if(!TreePointer-LeftSubtreeiInformationSign)=0)strcpy(ISarrayi.Code,TreePointer-C
29、ode);ISarrayi.CodeLength=TreePointer-CodeLength;return;return;if(TreePointer-LeftSubtree)/生成左子树编码:strcpy(tempstr,TreePointer-Code);strcat(tempstr,“2“);strcpy(TreePointer-LeftSubtree-Code,tempstr);TreePointer-LeftSubtree-CodeLength=TreePointer-CodeLength+1;Huffman_Code(TreePointer-LeftSubtree);if(Tre
30、ePointer-middleSubtree)/生成中子树编码:strcpy(tempstr,TreePointer-Code);strcat(tempstr,“1“);strcpy(TreePointer-middleSubtree-Code,tempstr);TreePointer-middleSubtree-CodeLength=TreePointer-CodeLength+1;Huffman_Code(TreePointer-middleSubtree);if(TreePointer-RightSubtree)/生成右子树编码:strcpy(tempstr,TreePointer-Co
31、de);strcat(tempstr,“0“);strcpy(TreePointer-RightSubtree-Code,tempstr);课程设计说明书(论文)第 12 页 共 15 页TreePointer-RightSubtree-CodeLength=TreePointer-CodeLength+1;Huffman_Code(TreePointer-RightSubtree);void CHuffman_3:Huffman_Coding()Huffman_Code(HuffTree);/编码结果分析void CHuffman_3:Huffman_CodeAnalyzing()/(1):
32、平均码长for(int i=0;iLeftSubtree);DestroyBTree(TreePointer-middleSubtree);DestroyBTree(TreePointer-RightSubtree);delete TreePointer;TreePointer = NULL;/主函数:void main()CHuffman_3 YYY;YYY.Huffman_Input();YYY.Huffman_Sort();YYY.Huffman_Tree();YYY.Huffman_Coding();YYY.Huffman_CodeAnalyzing();YYY.Huffman_Dis
33、play();课程设计说明书(论文)第 14 页 共 15 页图 3 程序运行结果总 结本次课程设计是以三进制哈夫曼编码来诠释多进制哈夫曼编码,其实不论是几进制的哈夫曼编码,只要掌握了编码的原理,是非常简单的。通过这次课程设计,我又重新的将信息论编码与设计的教材翻看了一遍,在网上也搜到了不少相关的知识,知识有提升不少。在这次课程设计中,最让人难懂的就是C+的编程,让我找了不少相关的书籍,上网查阅了不少的程序,对以前学过的编程又进一步巩固和提高了。在编程中,要涉及到编制哈夫曼树,平均码长,编码效率,信息率,信源熵。而且在程序中还要使用到一些函数,例如“for”、“ceil”函数等。哈夫曼码对信源的统计特性没有特殊要求,编码效率比较高,对编码设备的要求也比较简单,因此综合性能优于香农码和费诺码。哈夫曼编码在具体实课程设计说明书(论文)第 15 页 共 15 页用时,设备较复杂。在编码器中需要增加缓冲寄存器,因为每个信源符号所对应的码符号长度不一,负责会造成输入和输出不能保持平衡。参考文献1曹雪虹,张宗橙.信息论与编码.北京:清华大学出版社,2007.2王慧琴.数字图像处理 .北京:北京邮电大学出版社,2007.3刘宏.C+程序设计教程.武汉:武汉大学出版社,2005.4杨永国,张冬明.Visual C+6.0 实用教程.北京:清华大学出版社,2007.