数据结构与算法之并查集-2

95 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第19天,点击查看活动详情

✨欢迎关注🖱点赞🎀收藏⭐留言✒

🔮本文由京与旧铺原创,csdn首发!

😘系列专栏:java学习

💻首发时间:🎞2022年12月10日🎠

🀄如果觉得博主的文章还不错的话,请三连支持一下博主哦

🎧作者是一个新人,在很多方面还做的不好,欢迎大佬指正,一起学习哦,冲冲冲

🎀🎀🎀今日分享:这一年大概是我长这么大,最难熬的一年,也是让我成长最多的一年,感谢生活赐予我一场惊慌失措,但愿以后抬头由阳光

🐱‍💻导航小助手

2.2实现并查集查找根结点

在并查集中,由于对于非根结点,它指向的结点都不会是本身,严格来说没有进行优化前,某个元素会指向同一集合中的另外一个元素,就如下图所示,可以理解为一棵树: 0-2

2 所以并查集在查找的时候,如元素6,它指向3,我们可以先到3这个位置,通过3这个位置进而找到根结点。

0-3

对应的代码片段如下:

int find(int x) {
    while (x != p[x]) {
        x = p[x];
    }
    return x;
}
//递归形式
int find(int x) {
    if (x == p[x]) return x;
    return find(p[x]);
}

当树的高度比较高的时候,效率就比较低,数据大一点就会超时,因此我们可以做一个优化,就是在搜索根结点的时候,没找到一次根结点,我们就将所寻找路径上面所有元素都指向根结点,这样就与上面举例相同了,这个优化的过程也叫做路径压缩

3

0-6

这四个小组就对应着几个不同的集合,因为每个组员是记得他们的组长是谁的,所以我们可以通过询问组员就知道他们组长,进而就能知道该成员是哪一组的。

那么对应到并查集,我们知道当数组下标与元素相等时,该下标就是组长的编号也就是根结点,那我们可以先判断该元素的下标是否与存储的元素相同,如果不同,则跳到储存元素作为下标的位置,继续查找,找到根结点后,将搜索路径上的每个元素都置为该根结点的下标。

代码:

//查找某元素的根
int find(int x) 
{
    if (x != p[x]) p[x] = find(p[x]);
    return p[x];
}

2.3通过两个不同集合元素合并两个集合

这个就很简单了,我们只需要找到两个不相交集合元素的根结点,然后将其中一个根结点指向另外一个集合即可。

0-4

5

实现代码:

    //union合并两个集合
    void union(int a, int b)
    {
        int ar = find(a);
        int br = find(b);
        
        if (ar == br) return;
        
        p[br] = ar;
    }

到这里我们的一个并查集就实现完成了,下面通过一道模板题,来展示完整代码与验证。