• 霍夫曼编码


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

      某段文本中各个字母出现的频率分别是{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)

  • 相关阅读:
    Core2.0知识整理
    bootbox.js官方文档
    MongoDB分片详解
    MongoDB高可用集群+MMS集群监控搭建
    使用 AcceptTcpClientAsync 进行 异步 操作
    Windows证书操作
    SQL Server查询所有的表名、字段名、注释
    【转载】ASP.NET Core Web 支付功能接入 微信-扫码支付篇
    【转载】ASP.NET Core Web 支付功能接入 支付宝-电脑网页支付篇
    C#网络编程系列文章
  • 原文地址:https://www.cnblogs.com/xiehongfeng100/p/4796001.html
Copyright © 2020-2023  润新知