(数据结构)并查集

引言

并查集(Union-Find Set),顾名思义,是实现快速合并集合与查询元素所在集合的数据结构。
它在包括但不限于最小生成树Kruskal算法的众多算法中有很好的使用效果。

结构

形象地看,并查集是一个类似于森林的结构,同一个集合的元素都连在同一棵树上,查询操作即寻找树的根节点(唯一编码),合并即将一个集合的根连在另一棵树上。
抽象地看,这是一个记录父节点的数组(优化算法还包括这个集合的元素数量)。

性质

  • 该数组记录父节点编号。
  • 每个集合的根节点编号是其本身。

操作

  1. 查询元素所在集合
    根据性质,只需要依照沿着这个集合的树向上爬即可。
  2. 合并两个元素所在的集合
    根据操作1找到两个根节点后连接即可。

代码实现

基础版

//////////////////////////////////////////////////////////////////////
//Target: To implement the Union-Find Set
//@Author: Pisceskkk
//Date: 2019-2-24
//////////////////////////////////////////////////////////////////////

#define Max_N (int)1e6

int n,f[Max_N];

void init(int n){
    for(int i=1;i<=n;i++){
        f[i] = i;
    }
}

int find(int x){
    return (f[x) == x)?x:find(f[x]);
}

bool mege(int x,int y){
    x = find(x);
    y = find(y);
    if(x == y) return 0;
    f[x] = y;
    return 1;
}

问题来了:在特殊情况下,这棵树可能是一条长长的链。设链的最后一个结点为x,则
每次执行find(x)都会遍历整条链,效率十分低下。看上去是个很棘手的问题,其实改进方法
很简单。既然每棵树表示的只是一个集合,因此树的形态是无关紧要的,并不需要在“查
找”操作之后保持树的形态不变,只要顺便把遍历过的结点都改成树根的子结点,下次查找
就会快很多了。
——《算法竞赛入门经典》刘汝佳

猜你喜欢

转载自www.cnblogs.com/pisceskkk/p/10424444.html