前几天在论坛里看有人问的一个问题
有多个集合,每个集合中有或多或少个数;
凡事有过交集的集合都要合并到一起。
输入
{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();
}
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; }