浅谈Huffman树

所谓Huffman树,就是叶子结点带权的(K)叉树,假设每个叶子的权值为(v),到根的距离为(dep),那么最小化(sum v_i*dep_i)就是(Huffman)树的拿手好戏。

为了最小化这个值,显然我们应该尽量让权值大的叶子深度浅,合并果子就是一个典型(2)(Huffman)树问题。

那么对于(k)(Huffman)树呢?

我们以(3)(Huffman)树为例,有这么(6)个数:(1,2,3,5,8,9)

按照合并果子这题的思路,我们应该先花(6)体力合并(1,2,3),新序列为:(6,5,8,9)

然后花(19)体力合并(5,6,8),新序列为:(19,9)

最后花(28)体力合并(19,9),新序列是(28),一共用的体力为(53)

但是我们换一种方式合并:

(1,2,3,5,8,9)

(3,3,5,8,9)

(11,8,9)

(28)

一共用了(42)体力。

那么问题就出现了,显然对于(2)(Huffman)树的贪心策略不再适用于(k)(Huffman)树。

但是,是真的不适用么?

仔细考虑上面两个例子,在用了(53)体力的例子里,我们最后一步合并了(19,9),但其实我们还可以假设有一个权值为(0)的点在这一步被合并了。

但在用了(42)体力的例子里,我们第一步就把权值(0)给安排了。

所以对于(2)(Huffman)树的贪心策略还是有用的,不过我们忽视了权值为(0)的结点。因为(2)(Huffman)树怎么建都不会存在某一步被合并的结点少于(2),但是(k)(Huffman)树不一样,它必须满足((n-1)mod(k-1)=0)才会每一步合并的结点都不少于(k)。因为每次合并都会减少(k-1)个结点,一共会减少(n-1)个结点。如果不满足上述等式,我们只需要不断添加权值为(0)的结点直到它满足为止即可。

关于(k)(Huffman)树的建立,也可以按照合并果子一样用堆辅助即可。

原文地址:https://www.cnblogs.com/AKMer/p/10300870.html