update Huffman tree.

This commit is contained in:
Shine wOng
2019-06-01 15:45:44 +08:00
parent 3928c7ff9a
commit 5c40edcabf

View File

@@ -85,3 +85,29 @@ $$
此外对于二叉编码树任意第k个结点从一开始编号的左孩子是第2k个结点右孩子是第2k+1个结点如果左右孩子都存在的话。证明如下
设当前第k个结点至少有左子树高度为h所以本层在当前结点前面的结点有$k - 2^{h}$个,换算到下一层在当前结点左子结点前面的结点就有$2·(k - 2^{h})$个。本层在当前结点后面的结点有$2^{h+1} - 1 - k$个,这样在当前结点和子结点直接就相隔了$2·(k - 2^{h}) + 2^{h+1} - 1 - k = k - 1$个路人,所以当前结点的左结点位于第$2k$个,右节点在第$2k + 1$个。
> 哈夫曼编码(Huffman)
上面的最优编码树其实存在一些问题。它考虑了叶节点的平均深度,然后并没有考虑各个字符出现的频率往往是不一样的。例如英文字母`t`会比`j`出现的频率高出很多。在这样的情况下,最优编码树显然并不是最优,这让我想起之前的二分查找,看起来是平衡的,实际上却并不平衡,而后面的斐波拉契查找,看起来是不平衡的算法,实际上却是平衡的。这里也是同样的情况。
考虑字符出现频率来构造出来的最优编码树是Huffman编码树。Huffman编码树也有两个显而易见的性质
+ 双子性。同前
+ 层次性。这里的层次性与前面的层次性略有不同。这里的层次性是说拥有最低出现频率的两个字符必然同时位于编码树的最底层。为了便于讨论,不妨设他们俩互为兄弟结点。这个证明也是容易的,这里直接略过。
> Huffman编码树的构造。
首先将所有待编码的字符构造成只有一个元素的树,这样就形成了一个森林。每次取出森林中权值(出现频率)最低的两棵树将它们作为子树合并成一棵更高的树新生成树的权值为两棵字数之和。这样不断迭代知道森林中只剩下一棵树即为目标的Huffman编码树。
> Huffman编码树最优的证明。
针对某一个字符集$\Sigma$考虑一棵带权编码树T其带权平均叶节点深度(wald, weighted average leaf depth)为$wald(T)$。该字符集中权值最小的两个字符为`x`, `y`
考察另一个字符集$\Sigma^{'} = (\Sigma\\{x, y}) \cup {z}$,即字符集$\Sigma$排除掉`x`, `y`,在添加一个字符`z`,其权重等于`x`, `y`权重之和。其编码树为$T^{'}$。可以证明,如果$T^{'}$是最优带权编码树的话,那么$T$也是一棵最优带权编码树。
设$T^{'}$的带权平均叶节点深度为$wald(T^{'})$,那么$T$的平均带权叶节点深度
$$
wald(T) = wald(T^{'}) + W_a + W_b
$$
假设$T$并不是最优带权编码树,则存在一个比$T$更优的编码树$T_1$,满足$wald(T_1) < wald(T)$,那么将$T_1$中`x``y`结点合并成为`z`结点,对应的编码树$T_{1}^{'}$满足$wald(T_{1}^{'}) = wald(T_1) + W_a + W_b$,所以$T_{1}^{'}$是一棵比$T^{'}$更优的带权编码树,与假设矛盾。