什么是并查集
并查集:主要用于不相交集合的合并与查询。(如判断两个元素是否在同一集合中)
并查集主要操作
定义数组f[n],表示当前下标 i 所在的集合的祖先(树根)
- 初始化(拿1~5为例)
每个元素所在集合都只有本身,即每个元素都是树根(如图)。
-
查找
查找元素所在集合的根节点。 -
合并
将两个元素所在集合合并为一个集合(例子将1和3 2和3 3和5 4和5 合并 )
1和3合并,1所在集合的树根变为3;2和3合并,2所在集合的树根变为3;3和5合并,此时1、2和3都属于同一集合,1、2和3的树根均变为5,4和5合并,4所在集合的树根变为5(如图)。
代码片段
- 初始化
for(int i = 1;i <= n;i++) //初始化,每个函数自身为一个集合(很重要)
f[i] = i;
- 查询
int findx(int x) // 查找根节点
{
if(x == f[x])
return x;
return findx(f[x]);
}
- 合并
void uni(int x,int y) //合并
{
f[findx(x)] = findx(y);
}
并查集优化
- 朴素的并查集的时间主要浪费在查询操作上,原因在于当我们需要查询某个节点的根时,需要从该节点出发,不断的查询父亲元素直到找到根节点。
- 优化版的并查集是使用路径压缩的方法,将每个元素直接连到所在集合的根上(如图)。
- 拿例子来看,朴素版并查集查询元素1的根节点时,需要查询两次;而优化版并查集只需要查询1次。
代码片段(优化后)
int findx(int x) //查询函数
{
if(f[x] != x)
f[x] = findx(f[x]); // 路径压缩优化
return f[x];
}