考研数据结构之树与二叉树的应用:哈夫曼树、哈夫曼编码与并查集
考研数据结构之树与二叉树的应用:哈夫曼树、哈夫曼编码与并查集
树与二叉树不仅是数据结构的核心内容,其应用更是考研高频考点。本文聚焦哈夫曼树与哈夫曼编码(数据压缩)、并查集(动态连通性问题)两大应用,结合真题解析与代码实现,帮助考生深入掌握核心逻辑。
一、哈夫曼树与哈夫曼编码
1. 哈夫曼树的定义与构造
(1)基本概念
- 带权路径长度(WPL):树中所有叶子节点的权值乘以其到根节点的路径长度之和。
- 哈夫曼树(最优二叉树):给定一组权值,构造的WPL最小的二叉树。
特点:- 权值越大的节点离根节点越近。
- 哈夫曼树不唯一,但WPL相同。
(2)构造算法
通过贪心策略逐步合并最小权值节点:
- 初始化:将每个权值视为独立节点,构成森林。
- 重复以下步骤直至只剩一棵树:
- 从森林中选出两个权值最小的节点作为左右子树。
- 创建新节点作为它们的父节点,权值为两子节点之和。
- 将新节点加入森林。
示例:
权值集合{5, 3, 8, 2}
的构造过程:
Step 1: 选2和3 → 合并为5
Step 2: 选5和5 → 合并为10
Step 3: 合并10和8 → 最终WPL = 2*3 + 3*3 + 5*2 + 8*1 = 39
2. 哈夫曼编码
(1)编码规则
- 前缀编码:任一字符的编码都不是其他字符编码的前缀。
- 构造方法:
- 左分支标记为
0
,右分支标记为1
。 - 从根到叶子节点的路径即为该字符的编码。
- 左分支标记为
示例:
对字符A(5), B(3), C(8), D(2)
构造编码:
哈夫曼树结构: 18/ \8 10/ \5 5/ \2 3
编码结果:
D: 00, B: 01, A: 10, C: 1
(2)应用:数据压缩
- 压缩原理:高频字符用短编码,低频字符用长编码,减少总存储空间。
- 实际案例:BMP图片压缩中,统计各字节频率后构造哈夫曼编码,实现无损压缩。
3. 代码实现(C语言)
// 哈夫曼树节点定义
typedef struct HuffmanNode {int weight;struct HuffmanNode *lchild, *rchild;
} HuffmanNode;// 构造哈夫曼树
HuffmanNode* BuildHuffman(int weights[], int n) {// 使用优先队列(最小堆)实现// 伪代码:循环取最小两个节点合并,直至剩一个节点
}
二、并查集(Union-Find)
1. 数据结构与操作
(1)核心思想
- 父节点数组:用数组记录每个节点的父节点,根节点的父节点为自身。
- 路径压缩:查找时将路径上的节点直接指向根节点,优化后续操作。
(2)基本操作
- Find:查找节点的根(递归或迭代实现)。
- Union:合并两个集合(按秩合并或简单合并)。
代码示例:
int parent[MAX]; // 父节点数组int Find(int x) {if (parent[x] != x) parent[x] = Find(parent[x]); // 路径压缩return parent[x];
}void Union(int x, int y) {int rootX = Find(x), rootY = Find(y);if (rootX != rootY) parent[rootY] = rootX; // 简单合并
}
2. 应用场景
- 动态连通性问题:如判断图中是否存在环(Kruskal算法)。
- 社交网络:快速判断两人是否属于同一群体。
三、真题解析
1. 哈夫曼编码计算
题目(2023年真题,):
给定字符集
{A, B, C, D}
的频率为{5, 15, 45, 35}
,构造哈夫曼编码,并计算WPL。
解析:
- 构造哈夫曼树:
- 合并5和15 → 20
- 合并20和35 → 55
- 合并55和45 → 100
- 编码结果:
- A: 000, B: 001, C: 1, D: 01
- WPL:
5*3 + 15*3 + 45*1 + 35*2 = 205
。
2. 并查集时间复杂度
题目(经典真题,):
若并查集采用路径压缩和按秩合并优化,其
Find
和Union
操作的时间复杂度是多少?
答案:
均摊时间复杂度为O(α(n))
,其中α(n)
是阿克曼函数的反函数,可视为常数。
四、总结
- 哈夫曼树是贪心算法的典型应用,需掌握构造步骤与WPL计算。
- 并查集通过路径压缩和按秩合并实现高效动态连通性判断。
- 两者在数据压缩(哈夫曼编码)和图算法(Kruskal)中均有重要实践价值。