通俗易懂的并查集解释(附简单代码)

碰巧在学习kruskal算法来实现最小生成树,其中用到了并查集,然后详细研究了并查集。找到一篇好的链接。原文链接参考:https://blog.csdn.net/qq_41593380/article/details/81146850

具体并查集解释参考链接。代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int pre[1010]; //里面全是掌门
 
int unionsearch(int root)
{
    int son, tmp;
    son = root;
    while(root != pre[root]) //寻找掌门ing……
        root = pre[root];
    while(son != root) //路径压缩
    {
        tmp = pre[son];
        pre[son] = root;
        son = tmp;
    }
    return root; //掌门驾到~
}
 
int main()
{
    int num, road, total, i, start, end, root1, root2;
    while(scanf("%d%d", &num, &road) && num)
    {
        total = num - 1; //共num-1个门派
        for(i = 1; i <= num; ++i) //每条路都是掌门
            pre[i] = i;
        while(road--)
        {
            scanf("%d%d", &start, &end); //他俩要结拜
            root1 = unionsearch(start);
            root2 = unionsearch(end);
            if(root1 != root2) //掌门不同?踢馆!~
            {
                pre[root1] = root2;
                total--; //门派少一个,敌人(要建的路)就少一个
            }
        }
        printf("%d\n", total);//天下局势:还剩几个门派
    }
    return 0;
}
 

      代码重点应该在查找函数unionsearch(int root)以及合并函数(如下代码),当然这也是并查集含有的两项基本操作。main函数中代码写得有些啰嗦了,没仔细体会。这份代码固然逻辑清楚,代码简洁,但是还是有许多要改的地方。比如,在合并操作上,应该是将高度低的子树合并到高度高的子树,这样才能够保证合成树的高度尽可能低。从而能够满足高速查找操作。完美的并查集理论上是可以做到查找和合并都做到O(logn)的。

void join(int root1, int root2) //虚竹和周芷若做朋友
{
    int x, y;
    x = unionsearch(root1);//我老大是玄慈
    y = unionsearch(root2);//我老大是灭绝
    if(x != y) 
        pre[x] = y; //打一仗,谁赢就当对方老大
}
 

猜你喜欢

转载自blog.csdn.net/aishuirenjia/article/details/100147740
今日推荐