算法复习——贪心策略篇之霍夫曼编码
以下内容主要参考中国大学MOOC《算法设计与分析》,墙裂推荐希望入门算法的童鞋学习!
1. 问题背景
在计算机中,常用二进制串对不同字符进行编码,通常我们会使用编码树进行字符编码。对于编码树,
-
顶点到左结点的边标记为0,到右结点的边标记1,通过编码方案构造编码树;
-
每条根到叶子的路径对应每个字符的二进制串;
-
叶子结点的深度就是对应的字符编码的二进制串长度
一种编码方案构造出的编码树如图所示:

现给出另一种编码方式,如下表所示。
| a | b | c | d | e | f | |
|---|---|---|---|---|---|---|
| 编码方式1 | 0 | 101 | 100 | 111 | 1101 | 1100 |
| 编码方式2 | 0 | 1 | 00 | 01 | 10 | 11 |
但很容易发现,当我们在用编码方式2时,解码会出现问题,例如00110既可以解码成aabba,也可以解码成cfa,解码结果不唯一。其实,问题在于编码树我们要求的是一条根结点到叶子结点的路径对应一个字符的编码方式,但是如果根据编码方式2构造编码树,可以发现,a和b对应的结点不是编码树的叶子结点。
因此,可以提出前缀码的概念,即编码的任意前缀不是其他编码,则解码结果唯一,编码方式可行。
如果要求得到最优的编码方式,那不同的前缀码如何比较它们的优劣呢?我们可以通过比较编码后二进制串的总长,总长越短,说明这种编码方式越优。而编码后二进制的总长,依赖于待编码字符的频数,假设我们给出的带编码字符及其频数和两种不同的前缀码,如下表所示。
| a | b | c | d | e | f | |
|---|---|---|---|---|---|---|
| 频数(千次) | 45 | 13 | 12 | 16 | 9 | 5 |
| 前缀码1 | 0 | 101 | 100 | 111 | 1101 | 1100 |
| 前缀码2 | 1100 | 1101 | 111 | 100 | 101 | 0 |
通过计算可知,使用前缀码1编码后二进制串的总长是224000,使用前缀码2编码后二进制串的总长是348000,显然,前缀码1要优于前缀码2。
那么,本文要解决的问题就是如何求得编码后二进制串总长最短的前缀码。
2. 问题定义
最优前缀码问题(Optimal Prefix Code Problem)
输入:
- 字符数n以及各个字符的频数F = <f1, f2, …, fn>
输出:
- 解析结果唯一的二进制编码方案C = < c1, …, cn>,令
m i n ∑ i = 1 n ∣ c i ∣ ∗ f i , min\sum_{i=1}^{n}|c_{i}|*f~i~, mini=1∑n∣ci∣∗f

本文介绍了霍夫曼编码的基本概念及实现方法,包括问题背景、问题定义、贪心策略的应用等,并通过实例详细阐述了霍夫曼编码的构建过程及正确性证明。
最低0.47元/天 解锁文章
1356

被折叠的 条评论
为什么被折叠?



