数据结构与算法13-哈夫曼树及其应用

赫夫曼树及其应用

最基本的压缩编码方法----赫夫曼编码

定义与原理

我们先把这两棵二叉树简化成叶子结点带权的二叉树(注:树结点间的边相差的数叫做权Weight)

从树中一个结点到另一个结点之间的分支构成两个结点之间的路径,路径上的分支数目称做路径长度

如:二叉树a中,根结点到结点D的路径长度就为4,二叉树b中根结点到结点D的路径长度为2。

 

如图所示:其中A表示不及格、B表示及格、C表示中等、D表示良好、E表示优秀。每个叶子的分支线上的数字就是五个级别分制的成绩所占的百分比

树的路径长度就是从树根到每一结点的路径长度之和

二叉树a的树路径长度就为1+1+2+2+3+3+4+4=20

二叉树b的树路径长度就为1+2+3+3+2+1+2+2=16

若将树中结点赋给一个有着某种含义的数值,则这个数值称为该结点的权。结点的带权路径长度为:从根结点到该结点之间的路径长度与该结点的权的乘积。

 

如果考虑到带权的结点,结点的带权的路径长度为从该结点到树根之间的路径长度与结点上权的乘积。树的带权路径长度为树中所有叶子结点的带权路径长度之和。

假设有n个权值{W1,W2,…Wn},构造一棵有n个叶子结点的二叉树,每个叶子结点带权Wk,每个叶子的路径长度为lk,我们通常记作,带权路径长度WPL最小的二叉树称做赫夫曼树(最优二叉树)

 

有了上面的定义,我们来计算一下,上图中这两棵二叉的WPL

二叉树a

WPL=5x1+15x2+40x3+30x4+10x4=315

二叉树b

WPL=5x3+15x3+40x2+30x2+10x2=220

 

这样的结果意味着什么呢?如果我们现在有10000个学生的百分制成绩需要计算五级分制成绩,用二叉树a判断方法,需要做31500次比较,而二叉树b的判断只需要22000次比较,差不多少了三分之一量,在性能上提高不是一点点。

现在的问题就是,二叉树b这样的树是如何构造出来的,这样的二叉树是不是就是最估赫夫曼树呢? 赫夫曼给出如下解决方案

1.    先把有权值的叶子结点按照从小到大的顺序排列成一个有序序列,即A5,E10,B15,D30,C40。

2.    取头两个最小权值的结点作为一个新节点N1的两个子结点,注意相对较小的是左孩子,这里就是A为N1的左孩子,E为N1的右孩子。如图

 

新结点的权值 为两个叶子权值的和5+10=15

3.    将N1替换A与E,插入有序序列中,保持从小到大排列即:N115,B15,D30,C40

4.    重复步骤2.将N1与B作为一个新节点N2的两个结点。N2权值=15+15=30。

5.    将N2替换N1与B,插入有序序列中,保持从小到大排列。即N230,D30,C40.

6.    重复步骤2。将N2与D作为一个新节点N3的两个子结点。N3权值=30+30=60

7.    将N3替换N2与D,插入有序序列中,保持从小到大排列。C40,N360。

8.    重复步骤2。与C与N3作为一个新节点T的两个子结点,由于T即是根结点,完成赫夫曼树的构造

此时的下图的二叉树的带权路径长度

WPL=40x1+30x2+15x3+10x4+5x4=205。比之前的b二叉树的WPL值还少15。显然此时构造出来的二叉树才是最优的赫夫曼树。

 

不过现实总是比理想要复杂得多,上图虽然是二叉树,但由于每次判断都要两次比较

如根结点:就是a<80&& a>=70。总体性能上,反而不如b二叉树性能高。当然这并不是讨论的重点。

通过上例我们可以对构造赫夫曼树的赫夫曼算法描述。

1.    根据给定的n个权值{W1,W2,…,WN}构成的n棵二叉树集合F={T1,T2,...Tn},其中每棵二叉树Ti中只有一个带权为Wi的根结点,其左右子树均为空

2.    在F中选取两棵根结点可能会最小的树作为左右子树构造一棵新的二叉树,且置新的二叉树的根结点的权值为其左右子树上根结点的权值之和。

3.    在F中删除这两棵树,同时将新得到的二叉树加入F中。

4.    重复2和3步骤,直到F只含一棵树为止。这棵树便是赫夫曼树。

赫夫曼编码

比如我们有一段文字要传输给别人,显然用二进制的数字(0 ,1)来表示是很自然的想法。我们现在这段文字只有六个字母ABCDEF,那么我们可以用相应的二进制数据表示,如下:

 

 

这样真正传输的数据就是编码后的“000001010011100101”对方接收时可以按照3位一分来译码。如果一篇文章很长,这样的二进制串也将非常可怕。而且事实上,不管是英文、中文或是其它语言,字母或汉字的出现频率是不相同的,比如英语中的几个元音字母,中文的“的了有在”等汉字都是频率极高。

假设六个字母的频率为A 27,B 8,C  15,D  15,E  30,F   5合起来正好是100%。那就意味着,我们完全可以重新按照赫夫曼树来规划它们。我们将左图的可能会显示。右图为将权值左分支改为0,右分支改为1后的赫夫曼树。

 

此时,我们对这六个字母用其从树根到叶子所经过路径的0或1来编码,可以得到这样的定义。

 

 

原串二进制串是30个字符,新编码二进制串是25个字符。也就说是数据被压缩了,节约了大约17%的存储或传输成本。随着字符的增加和多字符权重的不同,这种压缩会更加显出其优势。

编码中非0即1,长短不等的话其实是容易混淆的,所以若要设计长短不等的编码,则必须是任一字符的编码都不是另一个字符的编码前缀,这种编码称做前缀编码

可这不能方便我们去解码,因此在解码时,还是要用到赫夫曼树,即发送方和接收方必须要约定好同样的赫夫曼编码规则。当我们接收时由原来的哈夫曼树可知。1001得到的字母是B     01得到的字母是A

 

结论:

一般地,设需要编码的字符集为{d1,d2…dn},各个字符在电文中出现的次数或频率集合为{w1,w2,…w3},以d1,d2,…dn作为叶子结点,以w1,w2,…wn作为相应叶子结点的权值来构造一棵赫夫曼树。规定赫夫曼树左分支代表0,右分支代表1,则从根结点到叶子结点所经过的路径分支组成的0和1的序列便为该结点对应字符的编码。这就是赫夫曼编码

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值