48-哈夫曼树

1. 什么是哈夫曼树

这里写图片描述
图1

  带权路径长度:设二叉树具有n个带权值的叶子节点,那么从根节点到各个叶子节点的路径长度与相应节点权值的乘积的和,叫做二叉树的带权路径长度(WPL)。

  比如在二叉树a中根节点到权值为7的节点的路径为4,根节点到权值为9的节点的路径也是为4,而在二叉树b中根节点到权值为2的节点的路径为3,根节点到权值为9的节点的路径为2 。也就是说,树的路径长度就是从树的根节点到每一节点的路径长度之和。


而带权路径长度(WPL)的公式为:

WPL=i=1nwili W P L = ∑ i = 1 n w i l i

n表示叶子节点的数目

w表示叶子节点k的权值

li l i 表示根节点到 ki k i 节点之间的路径长度(即从根节点到叶子节点的分支数)



  因此我们可以根据带权路径长度(WPL)的公式可以计算出二叉树a和二叉树b的带权路径长度,如图2所示:

这里写图片描述
图2

哈夫曼树的定义:具有最小带权路径长度的二叉树称为哈夫曼树(也称最优树)。

上图中a树的带权路径长度为89,b树的带权路径长度为60,因此根据哈夫曼树的定义,b树是哈夫曼树。

2. 构造哈夫曼树

构造哈夫曼树的原则:
  权值越大的叶子节点越靠近根节点。

  权值越小的叶子节点越远离根节点。


构造哈夫曼树的过程:
  (1)给定的n个权值 W1W2...Wn W 1 , W 2 , . . . , W n 构造n棵只有一个叶子节点的二叉树,从而得到一个二叉树的集合 F={T1T2...Tn} F = { T 1 , T 2 , . . . , T n }

  (2)在F中选取根节点的权值最小和次小的两棵二叉树作为左、右子树,构造一棵新的二叉树,新的二叉树根节点的权值为其左右子树根节点权值之和 。

  (3)在集合F中删除作为左、右子树的两棵二叉树,并将新建立的二叉树加入到集合F中 。

  (4)重复(2)、(3)两步,当F中只剩下一棵二叉树时,这棵二叉树便是所要建立的哈夫曼树 。

3. 构造哈夫曼树示例

这里写图片描述
图3

  在图3中,给定5个带权值(2,9,7,4,5)的二叉树,从中挑出权值最小和次小的两棵二叉树作为左、右子树,即权值为2的二叉树和权值为4的二叉树组合成一棵新的二叉树,新的二叉树根节点的权值为6(其左、右子树根节点权值之和得到的)。


这里写图片描述
图4

  然后将权值为2,权值为4的节点从集合F中删除,将权值为6的节点加入到集合F中,再从集合F中选取根节点权值为6和权值为5的两棵二叉树作为左、右子树,构造一棵新的二叉树,新的二叉树根节点的权值为11。


这里写图片描述
图5

然后重复(2),(3)步骤,直到集合F中剩下一棵二叉树,而这棵二叉树就是哈夫曼树,如图5所示 。

4. 应用—哈夫曼编码

  哈弗曼编码可应用于通信中的数据传输的最优化问题。现在有8个符号,即字符a到字符h,各个符号出现的概率分别为:

0.07 , 0.19 , 0.02 , 0.06 , 0.32 , 0.03 , 0.21 , 0.10

  于是我们需要确定各个符号的二进制编码,使编码后的代码长度最短,我们可以先采用等长编码方法,一个符号占用三个二进制位:

等长编码: a:0000 , b:0001 , c:0010 , d:0011 , e:0100 , f:0101 , g:0110 , h:0111

  从上面的等长编码中我们看到对于每个符号的编码都是4位,其中符号a的二进制编码为0000,符号b的二进制编码为0001…… 在等长编码中由于每个符号的编码都是4, 当我们要传输abcdefgh这一串数据时,得到的编码为:00000001001000110100010101100111,因此采用等长编码方案得到的二进制编码位数为32位,是比较长的,于是我们可以采用另一种方法:哈夫曼非等长编码。



哈夫曼非等长编码:

a:1010 b:00 c:10000 d:1001 e:11 f:10001 g:01 h:1011

  而在哈夫曼非等长编码中,对于出现频率非常高的符号来说,该符号的编码要尽可能的短,比如对于符号e来说,出现的频率为0.32,相对于其他符号的频率比较高,于是符号e的编码为11。对于符号b来说,也是如此,符号b的编码为00。而对于出现频率最低的符号f来说,符号f的编码为10001,它的编码可以稍微长一些。

  而采用哈夫曼非等长编码得到abcdefgh这串符号的编码为:1010001000010011110001011011,二进制编码位数为28。相比于采用等长编码得到位数要少一些。

  当传输的数据足够大时,采用哈夫曼非等长编码可以大大压缩数据,能节约数据的存储和传输,随着符号的增加和频率的不同,这种压缩会更加显示出优势。

  当接收到1010001000010011110001011011这样压缩过的编码时,我们需要怎么把它解码出来呢?而且编码中都是0和1,长短不等的话是很容易混淆的,所以若要设计长短不等的编码,则必须是任一字符的编码都不是另一个字符的编码的前缀,这种编码称作前缀编码。这样就不存在容易与1001混淆的100或10这样的编码。

  不光在编码时要用哈夫曼树,在解码时也需要用到哈夫曼树,即发送方和接收方必须约定好同样的哈弗曼编码规则。因此我们哈夫曼树的权值为各个符号的频率,并将左子树设置为0,右子树设置为1,哈夫曼树如下图所示:

这里写图片描述
图6

  当我们接收到1010001000010011110001011011时,根据事先约定好的哈夫曼树可知,1010得到的是第一个符号a,紧接着后面的00就是第二个符号b,其他符号以此类推。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值