并查集

Posted wizarderror

tags:

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

查集就是维护了几个动态的集合,集合中的每一个元素都标记了一个父节点,同一个集合的代表是相同的。当一个元素的父节点就是他本身时,它就是该集合的代表。

并查集有三种操作:

1. init(n):用于初始化集合,将每个元素的父节点设置为他本身。即表示当前一个元素为一个集合,互相没有联系

2. find(x):返回x所在集合的代表

3. unite(x,y):合并x,和y所在的集合。即把y的代表设置为x所在集合的代表

根据并查集判断两个元素是否有联系,只需判断他们是否在同一个集合里即可,也就是判断他们的代表是不是同一个

 

>>初始化

// 初始化n个元素
void init(int n)
{
    for (int i = 0; i < n; i++) {
        par[i] = i;
        rank[i] = 0;
    }
}

>>查询

//递归实现 
int find(int x) 
{  
    if (par[x]!=x) return find(par[x]);  
    else return x;
    //或者用return x == father[x] ? x: father[x] = find(father[x]);
}

//非递归路径压缩操作
int find(int x)
{
    int r = x;
    while(r!=par[r]) r = parent[r];
    //路径压缩
    int i = x, j;        
    while(i!=r) {   
        j = par[i];   //用j暂存par[i]的父节点
        par[i] = r;   //par[i]指向根节点
        i = j;        //i移到父节点
    }
    return r;           
}

>>合并

//合并x和y所在的集合
void unite(int x, int y)
{
    x = find(x);
    y = find(y); //将x和y的根分别赋值给x和y
    if (x==y) return; //如果x于y的根相同,则不必合并
 
    if (rank[x]<rank[y]) //合并时如果两棵树的高度不同,则将rank小的连到rank到的上面
        par[x] = y;
    else {
        par[y] = x;
        if (rank[x]==rank[y]) rank[x]++; //如果相同,则最高的高度合并之后需要在原来的基础上+1
    }
}

 参考自:

https://www.cnblogs.com/frankM/p/4399556.html

https://www.cnblogs.com/52dxer/p/10470004.html

https://www.cnblogs.com/sr1993/p/3697783.html

http://www.cnblogs.com/tanhehe/archive/2013/01/28/2883506.html

https://blog.csdn.net/zchahaha/article/details/51123557

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

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

树--12---并查集

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

并查集

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

并查集