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

来源:互联网 发布:foxmail知乎 编辑:程序博客网 时间:2024/06/01 08:32

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

有多个集合,每个集合中有或多或少个数;
凡事有过交集的集合都要合并到一起。
输入
{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;}
                                             
0 0