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