哈夫曼树算法例题详解
为了帮助大家更深入地理解哈夫曼树算法的实际应用,我们通过一道具体的例题进行详细讲解。
题目
已知字符集 {a, b, c, d, e} ,它们在某段文本中出现的频率分别为 \(10, 15, 12, 3, 40\) ,请构建哈夫曼树,并给出每个字符的哈夫曼编码。
解题步骤
1. 初始化节点
根据给定的字符及其频率,创建 5 个独立的节点,每个节点包含字符和对应的频率信息。此时,我们拥有 5 个只有一个节点的二叉树,如下表所示:
节点 |
字符 |
频率 |
1 |
a |
10 |
2 |
b |
15 |
3 |
c |
12 |
4 |
d |
3 |
5 |
e |
40 |
2. 构建最小堆
将这 5 个节点放入优先队列(最小堆)中,优先队列会依据节点的频率大小进行排序,频率小的节点位于堆顶。此时最小堆中的节点顺序为:节点 4(d,频率 3)、节点 1(a,频率 10)、节点 3(c,频率 12)、节点 2(b,频率 15)、节点 5(e,频率 40) 。
3. 合并节点
- 第一次合并:从最小堆中取出频率最小的两个节点,即节点 4(d,频率 3)和节点 1(a,频率 10) 。将它们作为新节点 6 的左右子节点(左右顺序不影响最终结果,这里假设 d 为左子节点,a 为右子节点),新节点 6 的频率为 \(3 + 10 = 13\) 。然后把新节点 6 放入最小堆中,此时最小堆中的节点顺序变为:节点 3(c,频率 12)、节点 6(频率 13)、节点 2(b,频率 15)、节点 5(e,频率 40) 。
- 第二次合并:再次从最小堆中取出频率最小的两个节点,即节点 3(c,频率 12)和节点 6(频率 13) 。将它们作为新节点 7 的左右子节点(假设 c 为左子节点,新节点 6 为右子节点),新节点 7 的频率为 \(12 + 13 = 25\) 。把新节点 7 放入最小堆,此时最小堆中的节点顺序为:节点 2(b,频率 15)、节点 7(频率 25)、节点 5(e,频率 40) 。
- 第三次合并:取出节点 2(b,频率 15)和节点 7(频率 25) ,将它们作为新节点 8 的左右子节点(假设 b 为左子节点,节点 7 为右子节点),新节点 8 的频率为 \(15 + 25 = 40\) 。把新节点 8 放入最小堆,此时最小堆中的节点顺序为:节点 5(e,频率 40)、节点 8(频率 40) 。
- 第四次合并:取出节点 5(e,频率 40)和节点 8(频率 40) ,将它们作为新节点 9(根节点)的左右子节点(假设节点 5 为左子节点,节点 8 为右子节点),新节点 9 的频率为 \(40 + 40 = 80\) 。此时最小堆中只剩下一个节点,即哈夫曼树的根节点,哈夫曼树构建完成。
用图表展示哈夫曼树的构建过程如下:
4. 生成哈夫曼编码
从哈夫曼树的根节点开始,向左走编码为 0,向右走编码为 1,直到到达叶子节点,路径上的 0 和 1 序列就是该叶子节点对应字符的哈夫曼编码。
- 对于字符 d:从根节点出发,向左走到节点 5,再向左走到节点 d,编码为 000。
- 对于字符 a:从根节点出发,向左走到节点 5,再向右走到节点 1,编码为 001。
- 对于字符 c:从根节点出发,向左走到节点 5,再向右走到节点 7,然后向左走到节点 c,编码为 010。
- 对于字符 b:从根节点出发,向左走到节点 5,再向右走到节点 7,然后向右走到节点 8,接着向左走到节点 b,编码为 011。
- 对于字符 e:从根节点出发,向右走到节点 8,编码为 1。
最终得到各字符的哈夫曼编码如下表所示:
字符 |
频率 |
哈夫曼编码 |
a |
10 |
001 |
b |
15 |
011 |
c |
12 |
010 |
d |
3 |
000 |
e |
40 |
1 |
通过这道例题,我们完整地展示了哈夫曼树算法从构建到编码的全过程。希望大家通过练习,能够熟练掌握哈夫曼树算法,并在实际问题中灵活运用它解决数据压缩等相关问题。