霍夫曼编码
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
霍夫曼编码
080212418高延邦
摘要:霍夫曼编码是一种常用的无损编码,他基于不同符号的概率分布,在信息源中出现概率越大的符号,相应的码越短;出现概率越小的符号,其码越长,从而达到用尽可能少的码符号表示源数据。本文首先介绍了信息论中的信息量,信息量是信息多少的量度。然后介绍了霍夫曼编码的应用,原理,具体步骤和特点。本文主要特色是结合实例十分详细地介绍了霍夫曼编码的原理,霍夫曼编码的方法,霍夫曼树的生成过程,霍夫曼编码的产生,霍夫曼表的构建,霍夫曼编码的结果以及怎么用计算机实现霍夫曼编码。
关键字:霍夫曼编码霍夫曼树最优二叉树无损压缩霍夫曼编码源代码
引言
霍夫曼编码(Huffman Coding)是一种编码方式,是可变字长编码(VLC)的一种。Huffman于1952年提出一种编码方法,该方法完全依据字符出现概率来构造异字头的平均长度最短的码字,有时称之为最佳编码。
一、霍夫曼编码理论基础
什么是信息量?信息量是信息多少的量度。1928年R.V.L.霍特莱首先提出信息定量化的初步设想,他将消息数的对数定义为信息量。若信源有m种消息,且每个消息是以相等可能产生的,则该信源的信息量可表示为I=-log(m)。
一个事件集合x1,x2,……x n,处于一个基本概率空间,其相应概率为p1,p2,……p n,且p1,p2,……p n 之和为1,每一个事件的信息量为I(x k)=-log n(p k),如定义在空间中的每一事件的概率不相等的平均不肯定程度或平均信息量叫做H,则H=E{I(x k)}=∑p k I(x k)=- ∑p k log a(p k)。
对于图像来说,n=2m个灰度级xi,则p(xi)为各灰度级出现的概率,熵即表示平均信息量为多少比特,换句话说,熵是编码所需比特数的下限,即编码所需的最少比特。编码一定要用不比熵少的比特数编码才能完全保持原图像的信息,这是图像压缩的下限。当a=2是,H的单位是比特。
二、霍夫曼编码简介
霍夫曼编码是1952年为文本文件而建立,是一种统计编码。霍夫曼编码是常用的无损编码方法,广泛应用于图像压缩技术。JPEG标准中的基准模式采用的就是霍夫曼编码。霍夫曼编码是不定长编码,即代表各元素的码字长度不等。该编码是基于不同符号的概率分布,在信息源中出现概率越大的符号,相应的码越短;出现概率越小的符号,其码越长,从而达到用尽可能少的码符号表示源数据。它在变长编码中是最佳的。在计算机信息处理中,“霍夫曼编码”是一种一致性编码法(又称"熵编码法")。
三、霍夫曼编码
(一)霍夫曼编码过程
设信息源空间为[A*P]:{A:a1 a2 ……an}{P(A):P(a1) P(a2) P(a3)……P(an)}其中P(ak)=1,先用r 个码的号码符号集X:{x1,x2,……xr}对信源A中的每一个符号ak进行编码。编码过程如下:
1.把信源符号ai按其出现的概率的大小顺序排列起来;
2.把最末两个具有最小概率的元素之概率加起来;
3.把该概率之和同其余概率由大到小排队,然后再把两个最小概率加起来,再排队;
4.重复步骤 (2) 、 (3), 直到概率和达到 1 为止 ;
5.在每次合并消息时,将被合并的消息赋以1和0或0和1;
6.寻找从每个信源符号到概率为1处的路径,记录下路径上的1和0;
7.对每个符号写出"1"、"0"序列(从码数的根到终节点)。
8.创建霍夫曼表。
9.压缩编码时,将码值用码字代替。
10.解码时,将码字用码值代替。
(二)霍夫曼树的构建
霍夫曼编码实际上构造了一个码树,码树从最上层的端点开始构造,直到树根结束,最后得到一个横放的码树即霍夫曼树。这里举个例子说明如何生成霍夫曼树。假设对由a1、a2、a3、a4、a5、a6、a7、a8八个信源符号组成的源信息字符串:“a1 a1 a2 a2 a3 a3 a3 a4 a4 a4 a4 a5 a5 a5 a6 a6 a6 a7 a7 a8”进行霍夫曼编码。首先应对信息中各数字出现的次数进行统计,得出各数字出现的相对概率。假设各数字出现的次数及概率如表1所示。
表一
具体过程是这样的,先将所有符号排成一行构成8个最底层节点。首先将这些节点中最小两个概率值相加:0.05+0.1=0.15, 得到新的节点,这时拥有的概率值为0.2, 0.1, 0.1, 0.15, 0.15, 0.15, 0.15。再将两个最小的概率值相加得到新的节点... ... 直到得到根节点概率为1.0为止。相加时,对于概率值相等的多个节点,可以任意选取。除根节点外,设节点左边分支为0,右边分支为1(也可以反过来)。根据表一生成的霍夫曼树如图1所示。
图1
对于各值(码值)的代码(码字)就是从根节点出发到底层节点所经历的分支序列。如a4的代码(码字)为00,a6的码字为111... ...通常a4和a6等称为码值,00和111等称为码字。所有码值和码字对应关系
如表2所示。
表2
(三)霍夫曼表
将所有码值和码字的关系整理成一张表,为了整字节输出码字,表中还含有各码字的长度。这种表就称为霍夫曼表。本例霍夫曼表如表3所示。
表3
进行压缩编码时,只要将码值用码字代替即可。所以源符编码为“0100100110111011011010000000011011011010000100001001”。
如果概率统计十分不准确,则压缩效率会很低。甚至起不到压缩效果。霍夫曼树平均码长是霍夫曼树
的带权路径长度,由于霍夫曼树是最优二叉树,带权路径长度最小的二叉树,故其压缩效果最好。
四、霍夫曼编码的特点
1.霍夫曼方法构造出来的码不是唯一的。
原因:
(1)在给两个分支赋值时, 可以是左支( 或上支) 为0, 也可以是右支( 或下支) 为0, 造成编码的
不唯一。
(2)当两个消息的概率相等时, 谁前谁后也是随机的, 构造出来的码字就不是唯一的。
2.霍夫曼编码码字字长参差不齐, 因此硬件实现起来不大方便。
3.霍夫曼编码对不同的信源的编码效率是不同的。
当信源概率是2 的负幂时, 霍夫曼码的编码效率达到100%;当信源概率相等时, 其编码效率最低。只有在概率分布很不均匀时, 霍夫曼编码才会收到显著的效果, 而在信源分布均匀的情况下, 一般不使用霍夫曼编码。
4.解码时, 必须参照这一霍夫曼编码表才能正确译码。
在信源的存储与传输过程中必须首先存储或传输这一霍夫曼编码表在实际计算压缩效果时, 必须考虑霍夫曼编码表占有的比特数。在某些应用场合, 信源概率服从于某一分布或存在一定规律( 这主要由大量的统计得到), 这样就可以在发送端和接收端固定霍夫曼编码表, 在传输数据时就省去了传输霍夫曼编码表, 这种方法称为霍夫曼编码表缺省使用。使用缺省的霍夫曼编码表有两点好处:降低了编码的时间, 改变了编码和解码的时间不对称性;
便于用硬件实现, 编码和解码电路相对简单。
五、霍夫曼编码代码:
#include
#include
#include
#include
using namespace std;
#define INF 0x7fffffff //无穷大
struct Huffmantree //霍夫曼树的节点
{
int weight;
int parent,ld,rd;
};
struct myNode
{
char ch;
int num;
};
struct mycode //字符和其对应的编码
{