Huffman算法

Huffman算法也是基本算法领域中经典的贪心算法之一。它起源于Huffman的研究生作业。我被其简单、优美深深地打动了。
该算法需要构造一个前缀码,即对每种字符采用一个编码,没有一个字符的编码是另外一个编码的前缀——这样解码时才是唯一的。

Huffman采取的算法: 不断找到出现次数最少的两个“节点”合并,合并的新节点作为一个“大节点”——节点的频率是被合并两个节点的频率和。合并节点的过程相当于找一个节点作为两个被合并节点的父亲。所以Huffman算法构造出来的是一棵二叉树,叶子节点都是原始字符的节点——从根到叶子节点的路径表示该字符的编码(例如左孩子编码为0,右孩子编码为1)。最终对一段文本的编码长度是每个字符编码长度与其频率的乘积之和。

Huffman算法_第1张图片

Huffman算法实现也比较简单——可以用最小堆实现。关于它的最优性证明,我认为不容忽视。

我们采用归纳法证明:

(1) n = 2 时,编码就是一个0和一个1,确实是最短的。

(2)假设n = k时成立,我们考虑n = k + 1时,我们假设w1, w2是频率最低的两个字符,也是Huffman算法最先合并的两个字符。

我们证明如下最优编码形成的树形结构中,w1和w2的深度一定相同。反正假设w1, w2最终的深度不同,例如w1的深度大于w2。因为编码是前缀码,没有一个编码是另外一个编码的前缀,我们把w1的深度减小1,也不会和其他编码冲突,而这种编码对文本编码的总长度显然更短,与我们假设最优编码矛盾。所以最优编码树中w1和w2的深度相同——如果最优树中w1,w2不是同一个节点的孩子,我们可以把它们调换成同一个节点的孩子,而编码的总长度不变——而这就相当于最先合并w1, w2为一个节点了。当少了一个节点后,根据归纳假设,我们知道Huffman算法一定是正确的。
另外,最优编码不唯一(例如当所有节点频率都相等的时候)。




你可能感兴趣的:(贪心,huffman算法)