数据结构与算法之并查集(union-find sets)

前几天在论坛里看有人问的一个问题

有多个集合,每个集合中有或多或少个数;
凡事有过交集的集合都要合并到一起。
输入
{1,3,4} {2,3,5} {6,7} {2,8} {3,9}
输出
{1,2,3,4,5,8,9} {6,7}


有大神说用并查集,然后我就搜索了以下,试着实现了一下。

在这个算法的适用场合有:求无向图的连通分量个数、最小公共祖先、带限制的作业排序、Kruskar算法求最小生成树。
更详细的可以参照如下链接:http://hi.baidu.com/fandywang_jlu/item/353f7ef010128814cf9f32fc


代码如下

void unionSets(int root1, int root2){
	s[root1] = root2;
}

int find(int x){
	if( s[x] == x){
		return x;
	}

	return find(s[x]);
}

void Init(){
	for(int i = 0; i < 10; i++)
		s[i] = i;
}

bool isContinue( int i, vector<int> &vec){
	for( size_t j = 0; j < vec.size(); j++){
		if( i == vec[j])
			return true;
	}

	return false;
}

void Print(){

	vector<int> already;
	for( int i = 1; i < 10 ; i++){
		if( isContinue(i, already)) continue;
		printf( "%d,", i);
		for( int j = i + 1; j < 10; j++){
			if( find(i) == find(j)){
				printf( "%d,", j);
				already.push_back(j);
			}
		}
		printf("\n");
	}

	getchar();

}

void Union( vector<vector<int>> &unions){

	Init();

	for( vector<vector<int>>::iterator itr = unions.begin(); itr != unions.end(); itr++){
		vector<int> arr = *itr;
		int pre = -1;
		for( vector<int>::iterator itr2 = arr.begin(); itr2 != arr.end(); itr2++){
			if( arr.size() > 1){
				if( itr2 == arr.begin() ){
					pre = *itr2;
					continue;
				}else{
					int a = find(pre);
					int b = find(*itr2);

					unionSets(a, b);
				}

				pre = *itr2;
			}else{
				s[*itr2] = *itr2;
			}
		}
	}

	Print();
}


main函数
void Union_Merge(){
	vector<int> nums;
	vector<vector<int>> unions;
	unions.resize(5);

	nums.push_back(1);
	nums.push_back(3);
	nums.push_back(4);
	unions[0] = nums;

	nums.clear();
	nums.push_back(2);
	nums.push_back(3);
	nums.push_back(5);
	unions[1] = nums;

	nums.clear();
	nums.push_back(6);
	nums.push_back(7);
	unions[2] = nums;

	nums.clear();
	nums.push_back(2);
	nums.push_back(8);
	unions[3] = nums;

	nums.clear();
	nums.push_back(3);
	nums.push_back(9);
	unions[4] = nums;

	Union(unions);
}

int main(){
	Union_Merge();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值