哈夫曼编码问题
问题描述
前缀编码:无任何字符的编码是另一个字符编码的前缀。
编码树的代价:
- 设C是字母表,任意的c属于C
- F(c)是c在文件中出现的频率
- DT (c)是叶子c在树T中的深度,即c的编码长度
- T的代价是编码一个文件的所有字符的代码位数: B(T)= ∑c∈C F(c) DT(c)
输入:字母表C = {c1,c2,...cn},频率表F = {F(c1),F(c2),...,F(cn)}
输出:具有最小代价B(T)的前缀编码树T
算法描述
1. 确定贪心思想
循环地在节点集合中选择具有最低频率的两个结点, 生成一棵子树,将该子树再放入到节点集合中,直至形成树。
2. 分析贪心选择性。
引理1:设C是字母表,任意的c∈C,c具有频率F(c), x、y 是C中具有最小频率的两个字符,则存在一个C的优化前缀树,x与y的编码都具有最大的长度,而且存在一 个C的优化前缀树一定含有一个子树为x与y生成的子树。
证明1:假设x的编码不具有最大的长度,那么,可以设设T是C的最优前缀树T,且b和c是具有最大深度的两个字符。T的简略图示如下:
节点b,c中至少有一个点的频率要不小于x的频率,不失一般性,假设该点为节点b。则f(b) ≥ f(x),可以构造构造T ',即交换树T中节点x和节点b的位置,其图示如下:
B(T) - B(T ')
=∑ F(c)DT(c) - ∑ F(c)DT '(c)
=F(x)DT(x) + F(b)DT(b) - F(x)DT '(x) - F(b)DT '(b)
=F(x)DT(x) + F(b)DT(b) - F(x)DT(b) - F(b)DT(x)
=[ F(b) - F(x) ][ DT(b) - DT(x) ] ≥ 0
即:B(T ) ≥ B(T ')
那么,至少存在编码树T '使得其代价不小于当前的最优编码树,这与假设矛盾,故而x的编码具有最大的长度。
同理,y的编码具有最大的长度。
那么,在一棵编码树中,具有最大长度的节点深度相同,即这两个节点要么位于同一棵子树的左右两支,要么位于一个树的同一层,而对于这两个节点位于一个树的同一层,可以进行节点交换,使得它们位于同一棵树的两支,这并不会改变树的代价。
3.分析优化子结构
引理2:设T是字母表C的优化前缀树,任意的c∈C,F(c) 是c在文件中出现的频率.设x、y是T中任意两个相邻叶结点,z是它们的父结点,则z作为频率是F(z)=F(x)+F(y)的字符,T '= T- {x,y}是字母表C '=C-{x,y}∪{z}的优化前缀编码树.
证明2:如果T '不是字母表C '=C-{x,y}∪{z}的优化前缀编码树。那么一定存在T '',B(T '') < B(T ')。而后将x节点与y节点加入T ''中,作为z的左右子节点,那么就可以得到C的一个前缀编码树T ''',那么接下来分析T 以及T '''之间的代价关系,寻找矛盾。
要分析T 以及T "'之间的代价关系,需要借助桥梁T '。
首先证明:B(T)=B(T ')+F(x)+F(y)。
证:任意的v∈C-{x,y}, dT(v)=dT'(v), f(v)dT(v)=f(v)dT’(v)
而B(T)与B(T ')之间只是差距了节点z以及节点x,y。
DT(x)=DT(y)=DT '(z)+1。
那么 F(x)DT(x) + F(y)DT(y)
=[ F(x) + F(y) ] * [DT '(z)+1]
=F(z)DT '(z) + F(x) + F(y)
方程两边同时加任意的v∈C-{x,y}的代价。
可得 B(T) = B(T ') + F(x) + F(y)
同理 B(T '") = B(T '') + F(x) + F(y)
而 B(T ') > B(T '') ,因为T ''是最优解
则 B(T '") < B(T) , 这与