• 并查集


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

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

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

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

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

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

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

    //并查集类声明
    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。
    */

    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的值。
    */

    void UFSet::SetUnion(int r1,int r2)
    {
    	uf[r1]=uf[r1]+uf[r2];
    	uf[r2]=r1;
    }
    

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

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

    主函数测试代码:

    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,简单而美妙的思维。

  • 相关阅读:
    阅读代码
    openSips
    rc.local 问题
    MyBatis框架使用(一)
    【数据结构杂谈】
    【AGC052A】
    【杜教筛学习笔记】
    CF618F Double Knapsack
    [NOI2016] 循环之美
    【BZOJ 4668 冷战】
  • 原文地址:https://www.cnblogs.com/fistao/p/3065176.html
Copyright © 2020-2023  润新知