1--并查集算法
并查集的核心功能有两个:第一个是判断两个元素是否属于同一个集合;第二个是合并两个元素,使其处在同一集合中;
#include <iostream>
#include <list>
#include <stack>
#include <unordered_map>
class UnionFindSet{
public:
// 初始化并查集,每个结点的所在集合的代表结点是其本身
UnionFindSet(std::list<int> nums){
for(int node : nums){
father_map.emplace(node, node);
}
}
// 寻找结点的代表结点
int FindFather(int node1){
std::stack<int> stk;
while(father_map[node1] != node1){
stk.push(node1);
node1 = father_map[node1];
}
while(!stk.empty()){
int tmp = stk.top();
stk.pop();
father_map[tmp] = node1;
}
return node1;
}
// 判断是否是一个集合
bool isSameSet(int node1, int node2){
if(father_map.find(node1) == father_map.end() || father_map.find(node2) == father_map.end()){
return false; // 结点不存在
}
// 具有相同的代表结点
if(FindFather(node1) == FindFather(node2)) return true;
return false;
}
// 合并两个元素
void Union(int node1, int node2){
// 已经属于一个集合了
if(isSameSet(node1, node2)) return;
// 找到两个集合的代表结点
int father1 = FindFather(node1);
int father2 = FindFather(node2);
// 将一个集合的结点指向另一个集合的代表结点
father_map[father1] = father2;
}
private:
std::unordered_map<int, int> father_map; // key表示结点,value表示结点的父亲(集合的代表结点)
};
int main(int argc, char * argv[]){
std::list<int> test = {1, 2, 3};
UnionFindSet S1(test);
bool res1 = S1.isSameSet(1, 2);
if (res1){
std::cout << "true" << std::endl;
}
else std::cout << "false" << std::endl;
S1.Union(1, 2);
bool res2 = S1.isSameSet(1, 2);
if (res2){
std::cout << "true" << std::endl;
}
else std::cout << "false" << std::endl;
return 0;
}