霍夫曼编码

  最近还接触到了一些关于霍夫曼编码的题目,如下一题:

  某段文本中各个字母出现的频率分别是{a:4,b:3,o:12,h:7,i:10},使用哈夫曼编码,则哪种是可能的编码:( )

  A  a(000)  b(001)  h(01)  i(10)  o(11)

  B  a(0000)  b(0001)  h(001)  o(01)  i(1)

  C  a(000)  b(001)  h(01)  i(10)  o(00)

  D  a(0000)  b(0001)  h(001)  o(000)  i(1)

  看完下文就知道上题的答案是什么了。

一个简明的例子

  这个例子摘自酷壳的一篇博文Huffman 编码压缩算法

  如果我们需要来压缩下面的字符串: “beep boop beer!” 

  首先,我们先计算出每个字符出现的次数,我们得到下面这样一张表 :

   

  然后,我们把这些东西放到Priority Queue中(用出现的次数据当 priority),我们可以看到,Priority Queue 是以Prioirry排序一个数组,如果Priority一样,会使用出现的次序排序:下面是我们得到的Priority Queue:

  

  接下来就是我们的算法——把这个Priority Queue 转成二叉树。我们始终从queue的头取两个元素来构造一个二叉树(第一个元素是左结点,第二个是右结点),并把这两个元素的priority相加,并放回Priority中(再次注意,这里的Priority就是字符出现的次数),然后,我们得到下面的数据图表:

  

  同样,我们再把前两个取出来,形成一个Priority为2+2=4的结点,然后再放回Priority Queue中 :

  

  继续我们的算法(我们可以看到,这是一种自底向上的建树的过程):

  

  

  

  最终我们会得到下面这样一棵二叉树:

  此时,我们把这个树的左支编码为0,右支编码为1,这样我们就可以遍历这棵树得到字符的编码,比如:‘b’的编码是 00,’p’的编码是101, ‘r’的编码是1000。我们可以看到出现频率越多的会越在上层,编码也越短,出现频率越少的就越在下层,编码也越长

  最终我们可以得到下面这张编码表:

  

  

  看完这个例子,我们也就知道本文开头的题目的答案是A了。

简要证明

  这里,我们只证明为什么出现频率低的节点要在霍夫曼树下层,而出现频率高的要在其上层呢?

  参考博文知其所以然(三):为什么算法这么难?

  假设这两个叶子节点的频率为f1和f2,深度为d1和d2,互换它们的时候,其他叶子节点的cost保持不变,令为常量C,那么互换前总cost为C+f1d1+f2d2,互换后为C+f1d2+f2d1,既然互换之后的树一定更”差“那么就是说f1d1+f2d2 < f1d2 + f2d1,简单变换一下就得到结论:f1(d1-d2)<f2(d1-d2),也就是说如果d1<d2,那么f1必然>f2,如果d1>d2,那么f1必然<f2。换言之就是叶子节点的深度越高,频率必须越低,否则就不可能是最优霍夫曼树。那么,之前我们觉得不那么显然的结论便呼之欲出了:频率最低的叶子节点必然位于树的最底层,频率最高的叶子节点必然位于树的最高层。

  注:cost of tree = Σ freq(i) * depth(i)

原文地址:https://www.cnblogs.com/xiehongfeng100/p/4796001.html