码迷,mamicode.com
首页 > 其他好文 > 详细

Huffman编码学习笔记

时间:2015-07-24 22:46:46      阅读:447      评论:0      收藏:0      [点我收藏+]

标签:贪心   dfs序   

主要是在学算导,觉得算导译到中国真是中国人民的福音。
一、编码
编码就是选择有意义的01串,令其首尾相接组成文本。我们并非可以随便挑选01串,原因在于它们是首尾相接的,这为我们识别造成了一些困难。比如说我们不能在文本000000中分清字符00与000.
一般我们使用的方式是定长字符;但更好的方式是前缀码,算导中写道”虽然我们这里不会证明,但与任何字符编码相比,前缀码确实可以保证达到最优数据压缩率。“,这显然是一个flag,将来一定会有比前缀码更好的编码方式的。
二、Huffman编码便是基于前缀码的,它试图依据一个文本找出其最优的前缀码以将其压缩。
显然文本长度等于各个字符长度乘以其各自的出现次数的总和。
考虑用一棵trie树做出所有01串字符集合,那么就成了各个叶子点的点权乘以其树高的和。
Huffman贪心基于排序不等式:
对于{a1,a2,...,an},满足aiai+1对于?1in,以及同样的{b1,b2,...,bn},满足bibi+1对于?1in,而{c1,c2,...,cn}是1~n的一个排列。
那么

i=1n(aibn?i+1)i=1n(aibci)i=1n(aibi)

证:
考虑后一个不等式,对于i≠j,如果bci>bcj,那么我们试图交换bcibcj,令bciaj相乘,bcjai相乘,我们考虑增量
Δ=aj?bci+ai?bcj?ai?bci?aj?bcj=ai?(bcj?bci)?aj?(bcj?bci)=(ai?aj)?(bcj?bci)0
那么我们不妨考虑插入排序的过程,将其{b1,b2,...,bn}排至与{a1,a2,...,an}顺序相乘而其和不下降。前一个式子是类似的。

而Huffman是怎么做的呢?他统计出所有字符的频率,每次选两个最小的,将其”合并“,直至只剩一个,那就是trie的根。其实合并等价于承认它们是兄弟,合并出来的节点便是它们的父亲,这样我们就可以像拓扑一样从叶子节点搞出整棵树来。
首先显然最优前缀码集合的trie树应该是一棵满二叉树,因为如果有一个节点的度为1的话,我们删掉它直接把它的儿子接给它的父亲显然会有更好的结果。
而如果我们规定内部节点的权值为其儿子节点权值和的话,文本长度其实也等于所有内部节点权值和,这是显而易见的,因为考虑到一个叶子节点会被考虑深度次。

那么我们已经它是如果搞出这个树的了,但是核心的问题在于,这为什么是正确的?
我们试图从Huffman给出的步骤倒推出它的正确性,这里我们会发现一个问题:先合并的两个最小的节点在trie树中的深度一定是最大的。这实际上与单调性有关。考虑Huffman合并的过程,它诞生的新节点的权值实际上是递增的。不妨设其为z=x+y,而下一次合并为z’=x’+y’(可能有x’=z或y’=z)那么显然z>x,又由于x和y是最小的两个权值,所以yy,所以zz,这也就是说对于内部节点z与z’,先合出来的也意味着会先被合并,也就是说后合出的节点深度加1意味着先合出来的节点深度至少加1,也就是说第一次合并——最小的那两个节点一定是深度最深的。
为什么令权值最小的节点深度最深可以得到最优前缀码呢?我们逆向考虑这个问题,考虑一棵最优前缀码trie树,显然令其深度与权值反序(排序不等式)深度与权值的乘积和最小。也就是说,存在这样一棵最优前缀码trie树,使得权值最小的两个叶子节点深度最大。
那么显然我们可以递归地考虑这个过程了,Huffman的正确性得证。

列一些挺好的算导练习:
1、假定我们有字母表C={0,1,···,n-1}上的一个最优前缀码,我们希望用最少的二进制位传输此编码。说明如何仅用2n?1+n?lgn?位表示C上的任意最优前缀码。(提示:通过对树的遍历,用2n-1位说明编码树的结构。)
这题我看了半天提示才明白。这个?lgn?也非常蛋疼,实在晕的话最好写俩数试一试。
实际上这个dfs序是极其特殊的,因为是一棵满二叉树,所以其实只用第一次访问时的dfs序即可。因为考虑遍历当前位,如果是0,那么一定是从上一个节点的儿子,而如果是1,则是当前深度最深的没满的节点的右儿子。
我一开始以为这里出了一点问题,因为我们是不用也没法记录根节点的,所以应该是2n?2+n?lgn?位。但是后来发现n=1的时候我的式子等于0,可它显然应该等于1.= =
2、假定一个数据文件由8位字符组成,其中所有256个字符出现的频率大致相同:最高的频率也低于最低频率的2倍。证明:在此情况下,赫夫曼编码并不比8位固定长度的编码高效。
赫夫曼编码从它出发点看就显然是最高效的前缀码,而前面也说过(虽然无法证明)前缀码拥有最高的压缩率,所以这其实就是证赫夫曼编码退化成了8位定长编码。
显然一上来我们会把所有的字符都两两合并起来,因为新合并出的字符一定大于原先的字符,所以我们要证第二层依然如此,即最高频率低于最低频率两倍。
设最低的两个频率为p1p2,最高的则为q1q2,那么显然第二层中,有q1+q22p1+2p12(p1+p2),即原命题得证。
这并不是什么高深的定理,但却为我们衡量某些东西提供了定量标准。很多题目中把定性转化为定量都是相当重要的一步(这是叫建模吧)。
3、证明:对于一个由随机生成的8位字符组成的文件,没变任何压缩方法可以望将其压缩,哪怕只是压缩以为。(提示:比较可能的文件数量和可能的编码文件数量。)
这个”望“显然应该是”期望“的意思。= =这显然应该是上一个题的推论,我只需要证最大者与最小者之比小于2即可。。然而我突然脑卡用期望最大最小值比起来了。。实际上我应该用期望最大频率比期望最小频率。
期望频率?不就是概率么!随机?那概率不都。。相等么!卧槽!= =

总结:
①推式子的时候一定要想明白意义。。不要瞎推啊。。
②一定要定性关系中寻找定量关系。
③以后要会用均值不等式了哦~
④要注意满二叉树dfs序的特殊性。
⑤以后剪枝、证明什么的别忘了均值不等式、排序不等式!(别的遇到再学吧。。)

版权声明:本文为博主原创文章,未经博主允许不得转载。

Huffman编码学习笔记

标签:贪心   dfs序   

原文地址:http://blog.csdn.net/ta201314/article/details/47045919

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!