【并查集】

一、什么是并查集

        并查集是一种用来管理元素分组情况的数据结构 ,可以查询元素a与元素b是否在同一个组中,也可以将两个不同的组进行合并操作(无法进行分割)。

        并查集是使用树形结构实现的,但不是二叉树。在树种每个元素对应着一个节点,同一组元素对应同一颗树上。

 

二、并查集的构造 

1、初始化并查集

        我们准备n个节点来表示n个元素,最开始时只有单独节点,不设置边,同时设置两个数组pre[]与rank[]分别用于记录前驱节点与树的高度。

int pre[MAX_N];
int rank[MAX_N];

void init(int n){
    for(int i=0; i<n; i++){
        pre[i] = i;
        rank[i] = 0;
    }
}

2、查询树的根

        在查询树的根时,我们会从一个指定元素x,利用pre[]找到它的前驱节点,继而逐步向上寻找直到找到元素x所在树的根。

        然而在向上搜索根的过程中我们发现,若是像左图中的情况,查询元素5的根时,会不断向上,直至找到根节点。当我们再次寻找元素5时,它仍旧会从底部不断向上寻找根,这会使得复杂度变高。因此我们不妨在第一次寻找根节点时,将指定的元素x的前驱节点直接更改为根节点,便于之后的查询,这种方法被称之为路径压缩。

        

 

int find(int x){
    //若指定元素本身就是根节点,返回指定元素
    if(pre[x]==x){//递归边界
       return x;
    }else{
        //递归,不断向上寻找前驱节点
        return pre[x] = find(pre[x]);
    }    
}

 3、合并

        因为并查集是树结构,我们可以将最顶点看作根节点。从一个组的根向另一个组的根连边,这样两棵树就合并为一棵树,这样操作结束后,就可以将两组元素合并到同一个组。为方便此操作,我们会比较树的高度,将树高较矮的树的根节点当作另一棵树的子节点连接上去(前提为合并的元素不在同一棵树上)。

void unite(int x,int y){
    x = find(x);//查找并记录x的根
    y = find(y);//查找并记录y的根
    if(x==y) return ;//判断是否是同一个根
    if(rank[x]>rank[y]){
        pre[y] = x;
    }else{
        //若树高相同,则让x所在的树的根附属到y的根下
        if(rank[x]==rank[y]) rank[y]++;
        pre[x] = y;
    }
}

4、判断 

        为查询两个节点是否属于同一个组,我们需要延树向上走,来查询包含这个元素的树的根是谁,若两个节点走到了同一个根那么就可以知道他们属于同一组。 

bool same(int x,int y){//判断元素x与元素y是否在同一个组中
    return find(x)==find(y);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值