不相交集合数据结构
概述
不相交集合数据结构(Disjoint-Set / Union-Find / 并查集)维护一组不相交动态集合 的划分,支持高效的合并(UNION)和查询(FIND-SET)操作。它是处理等价关系和连通分量问题的核心数据结构。
定义
不相交集合数据结构
维护一个元素集合 的一个划分(partition),即一组两两不相交的子集 ,满足:
- 对所有 ,
每个子集 称为一个集合(set),每个集合有一个代表(representative)来标识该集合。
三个核心操作
| 操作 | 语法 | 功能 |
|---|---|---|
| MAKE-SET | MAKE-SET(x) | 创建一个仅含元素 的新单元素集合 |
| UNION | UNION(x, y) | 将包含 的集合与包含 的集合合并 |
| FIND-SET | FIND-SET(x) | 返回包含 的集合的代表元素 |
操作的不变式
- FIND-SET(x) = FIND-SET(y) 当且仅当 和 属于同一个集合
- MAKE-SET(x) 之后, 单独构成一个集合,FIND-SET(x) = x
典型应用
- 连通分量维护:在无向图中,动态添加边时维护连通分量
- 等价关系维护:判断两个元素是否属于同一等价类
- 最小生成树(Kruskal 算法):判断加入边是否会形成环
- 迷宫生成:随机化 Prim/Kruskal 迷宫生成算法
发明历史
- 1973:Hopcroft & Ullman 提出按秩合并,达到
- 1975:Tarjan 提出路径压缩,与按秩合并结合达到
- 1989:Fredman & Saks 证明 的下界,确认 是最优的
四种实现的复杂度对比
*UNION 通过两次 FIND-SET + 一次 LINK 实现,均摊意义下的代价。
关键观察
最优实现(森林 + 按秩合并 + 路径压缩)的每次操作均摊代价为 ,其中 是反阿克曼函数。由于 对所有实际可能的 成立,因此在实践中可以视为 。
第21章:最小生成树
Kruskal算法是并查集最经典的应用场景。算法将图的边按权排序后逐条处理:对每条边 (u,v),使用 FIND-SET(u) ≠ FIND-SET(v) 判断 u 和 v 是否已在同一连通分量中。若不在同一分量,则 UNION(u,v) 合并两个分量并将边加入MST。使用按秩合并+路径压缩的并查集,Kruskal总时间 O(E α(V)),其中 α 是反阿克曼函数。