并查集

在一些应用问题中,如最小生成树算法中,需要将n个不同元素划分成一组不相交的集合。开始时,每个元素自成一个单元素集合,然后按照一定规律将归于同一组元素的集合合并。

实现这个功能的数据结构叫做并查集。

并查集需要支持下面三种操作:

1、Union 把子集2加入到子集1中。

2、Find 搜索单元素x所在集合,并返回该集合的名字。

3、UFSet 构造函数,主要完成初始化,将该分类数组的元素均置为-1。

下面介绍一个简单的并查集的实现,抓住主要思想:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//并查集类声明
class UFSet
{
public:
    UFSet(int n);
     
    int Search(int x);  //搜索
    void SetUnion(int r1,int r2);   //合并集合r2到r1
    void Output(int n)
    {
        for(int i=0;i<n;i++)
            cout<<uf[i]<<" ";
        cout<<endl;
    }
private:
    int *uf;
};

/*
建立并查集:
1、传入数组的个数,动态分配一个数组,并都初始化为-1。
2、将数组元素初始化为-1。
*/

1
2
3
4
5
6
UFSet::UFSet(int n)
{
    uf=new int[n];  //动态分配一个数组
    for(int i=0;i<n;i++)
        uf[i]=-1;   //将根结点初始化为-1,表示该集合中的个数
}

/*
合并函数算法:简单而美,绝了
1、将r1和r2的元素个数相加。
2、将r2的值赋值为r1的值。
*/

1
2
3
4
5
void UFSet::SetUnion(int r1,int r2)
{
    uf[r1]=uf[r1]+uf[r2];
    uf[r2]=r1;
}

/*
查找操作算法:很妙
1、沿父指针链一直向上,直到达到一个父指针域为负值的结点位置。
2、如果这个结点中的值大于或者等于0。
*/

1
2
3
4
5
6
int UFSet::Search(int x)
{
    while(uf[x]>=0)
        x=uf[x];    //循环搜索值域为0的位置
    return x;       //x即是要查找的位置,即数组的序号
}

主函数测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int _tmain(int argc, _TCHAR* argv[])
{
    cout<<"-----------并查集---------"<<endl;
    UFSet ufs(N);
    //分类
    ufs.SetUnion(0,6);
    ufs.SetUnion(0,7);
    ufs.SetUnion(0,8);
 
    ufs.SetUnion(1,4);
    ufs.SetUnion(1,9);
 
    ufs.SetUnion(2,3);
    ufs.SetUnion(2,5);
 
    ufs.Output(N);
 
    ufs.SetUnion(0,1);
    ufs.Output(N);
    return 0;
}

很happy,简单而美妙的思维。

posted @   李VS超  阅读(226)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示