左神基础班 - 并查集

这里要注意,我们有哈希表的时候,自己定义了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;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值