并查集

Posted tomato1001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了并查集相关的知识,希望对你有一定的参考价值。

并查集是一种用来管理元素分组情况的数据结构,可以高效的执行下面的操作:
1.查寻(find):查询元素a和b是否属于同一分组;
2.合并(union):将两个不同的分组合并为一个分组。
技术图片
注意并查集虽然可以进行合并操作,但是却无法进行分割操作。

并查集的结构

并查集使用树形结构实现,整个并查集由一颗或多棵树构成,每棵树代表一个分组。在并查集中,哪个节点是哪个节点的父亲以及树的形状等信息并不重要,整体形成一个树状结构才是关键。但是,在实际应用中,我们通常使用每个分组的根节点代表分组编号。

初始化

并查集初始状态是每个元素都属于自身的子集,即每个子集仅有一个元素。
技术图片

int fa[MAXN]; // 记录每个元素的父亲,初始化就是将每个元素的父亲设置为自身
void makeSet(int size) {
  for (int i = 1; i <= size; i++) 
    fa[i] = i;
}

查询分组

查找就是查看每个元素属于哪个分组,即通过该节点不断的查看自己的父亲,直到找到根节点。
技术图片

int find(int x) {
  if (fa[x] == x) 
    return x;
  return find(fa[x]);
}

合并

合并就是将两个分组合并为一个分组,首先找到两个分组的根,然后从一个分组的根向另一个分组的根两边,这样,两棵树就成为了一颗树,也就把两个组合并为一个组了。
技术图片

void unionSet(int x, int y) {
  x = find(x); 
  y = find(y); 
  if(x != y)
    fa[x] = y;  
}

查询

查询两个元素是否属于同一个分组,我们仅需找到两个元素所在分组的根节点,判断是否为同一个即可。

优化

并查集采用了树状结构实现,如果树的高度越来越高,查询的效率也会越来越低。为了避免退化,我们可以考虑将高度较小的分组合并到高度较大的分组,下面就是考虑了高度的合并。
技术图片
此外,在中间节点没有影响的情况下,也可以通过路径压缩来减小树的高度。路径压缩就是一旦向上走到了一次根节点,就把这个点到父亲的边改为直接连向根。
技术图片

int find(int x) {
  if (fa[x] == x) 
    return x;
  int p = find(fa[x]); 
  fa[x] = p;
  return p;
}

以上是关于并查集的主要内容,如果未能解决你的问题,请参考以下文章

想要学会并查集吗?看我四十行代码实现它

树--12---并查集

笔记并查集---无向图处理代码模板及类型题

并查集

力扣 每日一题 886. 可能的二分法难度:中等,rating: 1794(并查集 / 拆点优化的扩展域并查集)

并查集