并查集
概念
定义:并查集(Union-Find Set)是一种用于处理不相交集合的合并及查询问题的数据结构。
核心思想:维护若干个不相交的集合,支持快速判断两个元素是否属于同一集合,以及合并两个集合。
支持的操作
1. Find(x):查找操作
- 功能:查找元素 x 所属集合的代表元素(根节点)
- 用途:判断两个元素是否属于同一集合
2. Union(x, y):合并操作
- 功能:将元素 x 和 y 所在的两个集合合并为一个集合
- 前提:x 和 y 不在同一集合中
3. MakeSet(x):初始化操作
- 功能:创建一个只包含元素 x 的新集合
- 通常在初始化阶段批量执行
存储结构
数组表示法:
- parent[i]:存储节点 i 的父节点
- 根节点特征:parent[i] = i(自己指向自己)
- 路径表示:从任意节点向上追溯可到达根节点
辅助数组(用于优化):
- rank[i]:节点 i 的秩(子树高度的上界)
- size[i]:以节点 i 为根的子树大小
算法实现
基本实现
初始化:
MakeSet(x):
parent[x] = x查找操作:
Find(x):
if parent[x] ≠ x:
return Find(parent[x])
return x合并操作:
Union(x, y):
rootX = Find(x)
rootY = Find(y)
if rootX ≠ rootY:
parent[rootX] = rootY时间复杂度:
- Find 操作:O(h),其中 h 为树的高度
- Union 操作:O(h)
- 最坏情况:树退化为链,h = O(n)
优化实现
1. 路径压缩(Path Compression):
Find(x):
if parent[x] ≠ x:
parent[x] = Find(parent[x]) // 路径压缩
return parent[x]- 效果:将查找路径上的所有节点直接指向根节点
- 优势:后续查找操作时间复杂度接近 O(1)
2. 按秩合并(Union by Rank):
Union(x, y):
rootX = Find(x)
rootY = Find(y)
if rootX ≠ rootY:
if rank[rootX] < rank[rootY]:
parent[rootX] = rootY
else if rank[rootX] > rank[rootY]:
parent[rootY] = rootX
else:
parent[rootY] = rootX
rank[rootX]++- 原则:将秩小的树合并到秩大的树上
- 效果:控制树的高度,避免退化为链
3. 按大小合并(Union by Size):
Union(x, y):
rootX = Find(x)
rootY = Find(y)
if rootX ≠ rootY:
if size[rootX] < size[rootY]:
parent[rootX] = rootY
size[rootY] += size[rootX]
else:
parent[rootY] = rootX
size[rootX] += size[rootY]优化后时间复杂度:
- 单次操作:O(α(n)),其中α为阿克曼函数的反函数
- 实际意义:α(n) ≤ 5 对于所有实际应用,近似为常数时间
- m 次操作总时间:O(m·α(n))
空间复杂度:O(n)