这里要注意,我们有哈希表的时候,自己定义了Node,此时要定义该Node的哈希值怎么计算。
#include<iostream>
#include<unordered_map>
using namespace std;
struct Node{
char c;
//在并查集的 union_函数中用到了Node类型的比较操作,所以得自己重新定义
bool operator == (const Node& n) const{
return c == n.c;
}
bool operator != (const Node& n) const{
return c != n.c;
}
};
//由于使用了unoredred_map,以前我们使用基础的数据类型,系统能自己计算基础类型的hash值是什么,
//但现在我们要在哈希表中使用自定义的类型,所以得告诉哈希表该如何计算这一类型的哈希值
struct NodeHash{
size_t operator () (const Node& n) const{
return hash<int>()(n.c);
}
};
class UnionFindSet{
private:
unordered_map<Node, Node, NodeHash> fatherMap;
unordered_map<Node, int,NodeHash> sizeMap;
public:
//一开始,就要给我们所有的集合中的元素,然后让它们各自是一个集合,然后设每个集合的size为1
void setUnionFindSet(Node nodes[], int length){
for(int i=0; i<length; i++){
fatherMap[nodes[i]] = nodes[i];
sizeMap[nodes[i]] = 1;
}
}
//往上 用递归帮忙找代表节点
Node findDaiBiao(Node node){
Node father = fatherMap.find(node)->second;
if(father != node){
father = findDaiBiao(father);
}
fatherMap[node] = father;
return father;
}
//借助 找到的代表节点,判断两个节点是否在一个集合中
bool isSameSet(Node n1, Node n2){
Node daibiao_n1 = findDaiBiao(n1);
Node daibiao_n2 = findDaiBiao(n2);
if(daibiao_n1 != daibiao_n2)
return false;
return true;
}
//如果两个节点不在同一个集合里,那么我们就要把他们合并起来,size小的集合的代表节点,
//其parentmap中value改成size大的代表节点,更新size大的集合的size
void union_(Node n1, Node n2){
Node daibiao_n1 = findDaiBiao(n1);
Node daibiao_n2 = findDaiBiao(n2);
if(daibiao_n1 != daibiao_n2){
int size1 = sizeMap.find(daibiao_n1)->second;
int size2 = sizeMap.find(daibiao_n2)->second;
if(size1 < size2){
fatherMap[daibiao_n1]=daibiao_n2;
sizeMap[daibiao_n2]=(size1 + size2);
} else{
fatherMap[daibiao_n2]=daibiao_n1;
sizeMap[daibiao_n1]=(size1+size2);
}
}
}
};
int main(){
Node nodes[] = {{'a'}, {'b'}, {'c'}};
UnionFindSet ufset;
ufset.setUnionFindSet(nodes, 3);
cout << "一开始 的第一个节点和第二个节点是不是在一个集合里?" <<endl;
cout << ufset.isSameSet(nodes[0], nodes[1]) <<endl;
cout << "but,我使用union_函数后,是否在一起了呢?" <<endl;
ufset.union_(nodes[0],nodes[1]);
cout << ufset.isSameSet(nodes[0], nodes[1])<<endl;
return 0;
}