6/1-6/6并查集实现

用来解决连接问题

版本1:查找O(1),union O(N)   (只有一层)

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

class unionfind{
    int* id;   //表示数据的组
    int cnt;
public:
    unionfind(int n)
    {
        id=new int[n];
        for(int i=0;i<n;i++)  //初始化时每个元素单独一组
        {
            id[i]=i;
        }
        cnt=n;
    }

    int myfind(int p)
    {
        return id[p];
    }
    bool isconnected(int p,int q)
    {
        return myfind(p)==myfind(q);
    }

    void myunion(int p,int q)
    {
        int id1=id[p];
        int id2=id[q];
        if(id1==id2)
        {
            return ;
        }
        for(int i=0;i<cnt;i++)
        {
            if(id[i]==p)
            {
                id[i]=q;
            }
        }
        return ;
    }
};


int main()
{
    unionfind uf(100);
    cout<<uf.isconnected(1,2)<<endl;
    uf.myunion(1,2);
    cout<<uf.isconnected(1,2)<<endl;
    return 0;
}

版本2:union O(1) find O(N)   (有很多层)

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

class unionfind{
    int* parent;   //表示数据的父节点
    int cnt;
public:
    unionfind(int n)
    {
        parent=new int[n];
        for(int i=0;i<n;i++)  //初始化时每个元素单独一组
        {
            parent[i]=i;
        }
        cnt=n;
    }

    int myfind(int p)   //找根节点
    {
        while(p!=parent[p])
        {
            p=parent[p];
        }
        return p;
    }
    bool isconnected(int p,int q)
    {
        return myfind(p)==myfind(q);  //根节点相同的话,是联通的
    }

    void myunion(int p,int q)
    {
        int root1=myfind(p);
        int root2=myfind(q);
        if(root1==root2)
        {
            return ;
        }
        parent[root1]=root2;
        return ;
    }
};

int main()
{
    unionfind uf(100);
    cout<<uf.isconnected(1,2)<<endl;
    uf.myunion(1,2);
    cout<<uf.isconnected(1,2)<<endl;
    return 0;
}

版本3:基于size的优化

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

class unionfind{
    int* parent;   //表示数据的父节点
    int* sz;
    int cnt;
public:
    unionfind(int n)
    {
        parent=new int[n];
        sz=new int[n];  //以i为根的集合中元素个数
        for(int i=0;i<n;i++)  //初始化时每个元素单独一组
        {
            parent[i]=i;
            sz[i]=1;
        }
        cnt=n;
    }

    int myfind(int p)   //找根节点
    {
        while(p!=parent[p])
        {
            p=parent[p];
        }
        return p;
    }
    bool isconnected(int p,int q)
    {
        return myfind(p)==myfind(q);  //根节点相同的话,是联通的
    }

    void myunion(int p,int q)
    {
        int root1=myfind(p);
        int root2=myfind(q);
        if(root1==root2)
        {
            return ;
        }
        else if(sz[root1]<sz[root2])
        {
            parent[root1]=root2;
            sz[root2]+=sz[root1];
        }
        else
        {
            parent[root2]=root1;
            sz[root1]+=sz[root2];

        }

        return ;
    }
};

int main()
{
    unionfind uf(100);
    cout<<uf.isconnected(1,2)<<endl;
    uf.myunion(1,2);
    cout<<uf.isconnected(1,2)<<endl;
    return 0;
}

版本4:基于rank的优化:

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

class unionfind{
    int* parent;   //表示数据的父节点
    int* myrank;//以i为根的集合表示的树的层数
    int cnt;
public:
    unionfind(int n)
    {
        parent=new int[n];
        myrank=new int[n];
        for(int i=0;i<n;i++)  //初始化时每个元素单独一组
        {
            parent[i]=i;
            myrank[i]=1;
        }
        cnt=n;
    }

    int myfind(int p)   //找根节点
    {
        while(p!=parent[p])
        {
            p=parent[p];
        }
        return p;
    }
    bool isconnected(int p,int q)
    {
        return myfind(p)==myfind(q);  //根节点相同的话,是联通的
    }

    void myunion(int p,int q)
    {
        int root1=myfind(p);
        int root2=myfind(q);
        if(root1==root2)
        {
            return ;
        }
        else if(myrank[root1]<myrank[root2])
        {
            parent[root1]=root2;
            ++myrank[root2];
        }
        else
        {
            parent[root2]=root1;
            ++myrank[root1];

        }

        return ;
    }
};

int main()
{
    unionfind uf(100);
    cout<<uf.isconnected(1,2)<<endl;
    uf.myunion(1,2);
    cout<<uf.isconnected(1,2)<<endl;
    return 0;
}

前两个版本针对union进行优化,下面的版本针对find进行优化

版本5:路径压缩

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

class unionfind{
    int* parent;   //表示数据的父节点
    int* myrank;//以i为根的集合表示的树的层数
    int cnt;
public:
    unionfind(int n)
    {
        parent=new int[n];
        myrank=new int[n];
        for(int i=0;i<n;i++)  //初始化时每个元素单独一组
        {
            parent[i]=i;
            myrank[i]=1;
        }
        cnt=n;
    }

    int myfind(int p)   //找根节点
    {
        while(p!=parent[p])
        {
            parent[p]=parent[parent[p]];   //路径压缩 将p的父亲设置成p的父亲的父亲
            p=parent[p];
        }
        return p;
    }
    bool isconnected(int p,int q)
    {
        return myfind(p)==myfind(q);  //根节点相同的话,是联通的
    }

    void myunion(int p,int q)
    {
        int root1=myfind(p);
        int root2=myfind(q);
        if(root1==root2)
        {
            return ;
        }
        else if(myrank[root1]<myrank[root2])
        {
            parent[root1]=root2;
            ++myrank[root2];
        }
        else
        {
            parent[root2]=root1;
            ++myrank[root1];

        }

        return ;
    }
};

int main()
{
    unionfind uf(100);
    cout<<uf.isconnected(1,2)<<endl;
    uf.myunion(1,2);
    cout<<uf.isconnected(1,2)<<endl;
    return 0;
}

版本6:进一步路径压缩

#include <iostream>
#include <bits/stdc++.h>
using namespace std;

class unionfind{
    int* parent;   //表示数据的父节点
    int* myrank;//以i为根的集合表示的树的层数
    int cnt;
public:
    unionfind(int n)
    {
        parent=new int[n];
        myrank=new int[n];
        for(int i=0;i<n;i++)  //初始化时每个元素单独一组
        {
            parent[i]=i;
            myrank[i]=1;
        }
        cnt=n;
    }

    int myfind(int p)   //找根节点
    {
        if(p!=parent[p])
        {
            parent[p]=myfind(parent[p]);   //压缩成只有两层
        }
        return parent[p];
    }
    bool isconnected(int p,int q)
    {
        return myfind(p)==myfind(q);  //根节点相同的话,是联通的
    }

    void myunion(int p,int q)
    {
        int root1=myfind(p);
        int root2=myfind(q);
        if(root1==root2)
        {
            return ;
        }
        else if(myrank[root1]<myrank[root2])
        {
            parent[root1]=root2;
            ++myrank[root2];
        }
        else
        {
            parent[root2]=root1;
            ++myrank[root1];

        }

        return ;
    }
};

int main()
{
    unionfind uf(100);
    cout<<uf.isconnected(1,2)<<endl;
    uf.myunion(1,2);
    cout<<uf.isconnected(1,2)<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值