并查集

在一些应用问题中,如最小生成树算法中,需要将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,简单而美妙的思维。

原文地址:https://www.cnblogs.com/fistao/p/3065176.html