哈弗曼编码及实现

  • 格式:doc
  • 大小:189.00 KB
  • 文档页数:13

1 数据结构课程设计报告 题目:哈弗曼编码及实现 学校:东华理工大学 学院:软件学院 专业:网络工程 姓名:万呈华 班级:1122101 学号:201120210130 2

目 录 1. 课题描述.................................................................................. ..................................................3 2. 哈夫曼编码的原理.....................................................................................................................4 2.1 哈夫曼编码的构造过程……………………………..………………….………............4 2.2 哈夫曼编码的应用举例…………………………….……………..……….……...........4 3. 哈夫曼编码的实现过程.............................................................................................................7 3.1 软件介绍 ........................................................................................................................ 7 3.2 设计内容 ........................................................................................................................ 7 3.2 设计步骤…………………………………………………………………………….......7 4. 程序运行结果分析…………………………………………………………...........................12 .总 结.............................................................................................................................................. 13 3

1 课题描述 哈夫曼编码是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最 小的二叉树,经常应用于数据压缩。在计算机信息处理中, “哈夫曼编码”是一 种一致性编码法(又称"熵编码法") ,用于数据的无损耗压缩。这一术语是指使 用一张特别的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码 表的特别之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现 概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编 码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的) 。 一.设计目的

1、深刻理解信源编码的基本思想与目的; 2、理解哈夫曼编码方法的基本过程与特点; 3、提高综合运用所学理论知识独立分析和解决问题的能力; 4、使用 MATLAB 或其他语言进行编程。

二.设计内容 假设已知一个信源的各符号概率,编写适当函数,对其进行哈夫曼编码,得 出码字,平均码长和编码效率,总结此编码方法的特点和应用。

三.设计要求 1、编写的函数要有通用性;

2、信源可以自由选择,符号信源与图像信源均可。 4

3、设计条件 计算机、MATLAB 或其他语言环境 2 哈夫曼编码的原理 2.1 哈夫曼编码的构造过程 实现哈夫曼算法的大致描述为: 初始化:将 2n-1 个结点的三个指针域的值置为空(可用-1 表 示),权值为 0; 输入:读入 n 个叶结点的权值存入向量的前个分量中,即形成有个结点的森 林(一个结点为一棵树); 排序:按权值排序(从小到大) 合并:把前两棵树组成一棵新树,放回森林,直至形成一棵树 最后输出哈夫曼编码

2.2 哈夫曼编码应用举例 哈夫曼树被广泛的应用在各种技术中,其中最典型的就是在编码技术上的应 用。利用哈夫曼树,我们可以得到平均长度最短的编码。这里我们以计算机操作 码的优化问题为例来分析说明。 研究操作码的优化问题主要是为了缩短指令字的长度,减少程序的总长度以 及增加指令所能表示的操作信息和地址信息。 要对操作码进行优化, 就要知道每4种操作指令在程序中的使用频率。 这一般是通过对大量已有的典型程序进行统计 得到的。 5

由于计算机内部只能识别 0、 代码, 1 所以若采用定长操作码, 则需要 3 位 3 (2 =8)。显然,有一条编码没有作用,这是一种浪费。一段程序中若有 n 条指令, 那么程序的总位数为 3×n。为了充分地利用编码信息和减少程序的总位数,我们 可以采用变长编码。如果对每一条指令指定一条编码,使得这些编码互不相同且 最短,是否可以满足要求呢?即是否可以如下表所示这样编码呢?

这样虽然可以使得程序的总位数达到最小,但机器却无法解码。例如对编码 串 0010110 该怎么识别呢?第一个 0 可以识别为 I1, 也可以和第二个 0 组成的串 00 一起被识别为 I3,还可以将前三位识别为 I6,这样一来,这个编码串就有多种 译法。因此,若要设计变长的编码,则这种编码必须满足这样一个条件:任意一 个编码不能成为其它任意编码的前缀。我们把满足这个条件的编码叫做前缀编 码。

利用哈夫曼算法,可以使我们设计出最优的前缀编码。首先,我们以每条指 令的使用频率为权值构造哈夫曼树, 6

如下图 6.27 所示: 对于该二叉树,我们可以规定向左的分支标记为 1,向右的分支标记为 0。这 样,从根结点开始,沿线到达各频度指令对应的叶结点,所经过的分支代码序列 就构成了相应频度指令的哈夫曼编码,如下图所示:

可以验证,该编码是前缀编码。若一段程序有 1000 条指令,其中 I1 大约有 400 条,I2 大约有 300 条,I3 大约有 150,I4 大约有 50 条,I5 大约有 40,I6 大约 I 对于定长编码, 该段程序的总位数大约为 3×1000=3000。 有 30, 7 大约有 30 条。 7

采用哈夫曼编码后,该段程序的总位数大约为 1×400+2×300+3×150+5×(50 +40+30+30)=2200。可见,哈夫曼编码中虽然大部分编码的长度大于定长编 码的长度 3, 却使得程序的总位数变小了。 可以算出该哈夫曼编码的平均码长为:

3 哈夫曼编码的实现过程 3.1 软件介绍 MATLAB 以矩阵作为基本编程单元,它提供了各种矩阵的运算与操作,并有 较强的绘图功能。MATLAB 集科学计算、图像处理、声音处理于一身,是一个 高度的集成系统,有良好的用户界面,并有良好的帮助功能。MATLAB 不仅流 行于控制界,在机械工程、生物工程、语音处理、图像处理、信号分析、计算机 技术等各行各业中都有极广泛的应用。MATLAB 语言的特点 : 1.编程效率高 2.用户使用方便 3.扩充能力强 和数组运算 3.方便的绘图功能 5.语句简单,内涵丰富 6.高效方便的矩阵

3.2 设计内容 已知一个信源的各符号概率,编写适当函数,对其进行哈夫曼编码,得出码 字,平均码长和编码效率,总结此编码方法的特点和应用。

3.3 设计步骤 MATLAB 的操作界面 MATLAB 操作界面主要分为:任务栏、命令窗、命令 历史窗、 8

当前目录浏览器、工作空间浏览器及一个“启动按钮” 任务栏:位于软件的正上方。各个菜单分别为:文件、编辑、视窗、调试、 桌面、窗体、帮助这几个窗口,点击每个窗口可以选择需要的操作。 命令窗(Command Window):位于软件操作界面的右侧。在此窗口里,可以输 入各种指令、函数、变量表达式并进行各种操作。该窗口用于输入命令并显示除 图形以外的所有执行结果。窗口中的“>>”为命令提示符,直接在其后面输入命令并按下回车键后,会出现计算结果在命令后面。 命令历史窗(Command History): 位于软件操作界面的左下方。 这个窗口记录 了命令窗口已经运行过的所有命令(指令、函数等) ,允许用户对这些命令进行 选择、复制。 程序如下: (假定随机信源为 3,1,3,2,4,3,2,1,2,3)

clear all; I=[3,1,3,2,4,3,2,1,2,3]; len=length(I); t=2; biaozhi=0; b(1)=I(1); for i=2:len for j=1:i-1 if I(j)==I(i) biaozhi=1; break; end End if biaozhi==0 b(t)=I(i); t=t+1; End biaozhi=0; end 9

fprintf('信源总长度:\n'); disp(len); %信源总长度 fprintf('字符:\n'); disp(b ); L=length(b); for i=1:L a=0; for j=1:len if b(i)==I(j) a=a+1; count(i)=a; End end end count=count/len;%各字符概率 fprintf('各字符概率:\n'); disp(count); p=count; s=0; l=0; H=0; N=length(p); for i=1:N H=H+(- p(i)*log2(p(i)));%计算信源信息熵 end fprintf('信源信息熵:\n'); disp(H); tic; for i=1:N-1 %按概率分布大小对信源排序 for j=i+1:N