并查集的实现和优化以及使用

本文详细介绍了并查集的数据结构及其C++实现,包括findhead()、union_set()和isSameset()三个核心函数。通过示例代码展示了如何初始化、查找根节点、合并集合以及判断元素是否属于同一集合。并查集是一种用于维护不相交集合的高效数据结构,主要应用于路径压缩和按秩合并策略以提高效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

并查集的代码实现

并查集主要由三部分接口函数构成,分别是findhead(),union_set()和Is_sameset()构成。findhead主要是用来寻找同集合中的头集合,union_set主要是用来合并两个集合,is_Sameset主要是判断两个数据是否是同一个集合。

unionset的构造

class UnionFindSet {
	vector<int> parent; // 用来存放它的上层节点
	vector<int> rank;   // 存放根节点的尺寸,用深度来表示
public:
	UnionFindSet(vector<int>& vec);

	int findhead(int nums);
	void union_set(int node1, int node2);
	bool isSameset(int num1, int num2);
};

UnionFindSet::UnionFindSet(vector<int>& vec) {    //初始化
	for (auto& it : vec) {
		parent[it] = it;    //初始化父路径
		rank[it] = it;		//初始化秩
	}
}

parent用来存放子节点的头结点head,初始化的是否每一个child节点的parent节点都是自己本身。

findhead函数

找到节点的最终父节点,并且进行路径压缩,使得所有的子节点直接指向父节点,这样就可以大大提高子节点寻找父节点的效率。

int UnionFindSet::findhead(int num) {    //查找根节点,也就是它的老大,并且压缩路径,压缩到只有一层
	int child = num;

	while (parent[num] != num) {   //此循环退出时,num是根节点
		num = parent[num];    
	}

	while (child != num) {         //再走一遍上面的过程。 
		int par = parent[child];   //保存父节点

		parent[child] = num;    //child的父节点指向num;

		child = par;
	}
	return num;
	
}

合并两个数到同一个集合中

void UnionFindSet::union_set(int node1, int node2) {
	int Pa1 = findhead(node1);
	int Pa2 = findhead(node2);

	if (Pa1 == Pa2) return;
	if (rank[Pa1] > rank[Pa2]) {
		parent[Pa2] = Pa1;     //合并Pa2到Pa1
	}
	else if (rank[Pa1]<rank[Pa2]){
		parent[Pa1] = Pa2;
	}
	else {
		parent[Pa1] = Pa2;
		rank[Pa2] += 1;
	}
}

首先通过调用findhead找到头结点,然后根据节点的秩的不同来合并两个节点。

全部代码

!= num) {   //此循环退出时,num是根节点
		num = parent[num];    
	}

	while (child != num) {         //再走一遍上面的过程。 
		int par = parent[child];   //保存父节点

		parent[child] = num;    //child的父节点指向num;

		child = par;
	}
	return num;
	
}

void UnionFindSet::union_set(int node1, int node2) {
	int Pa1 = findhead(node1);
	int Pa2 = findhead(node2);

	if (Pa1 == Pa2) return;
	if (rank[Pa1] > rank[Pa2]) {
		parent[Pa2] = Pa1;     //合并Pa2到Pa1
	}
	else if (rank[Pa1]<rank[Pa2]){
		parent[Pa1] = Pa2;
	}
	else {
		parent[Pa1] = Pa2;
		rank[Pa2] += 1;
	}
}

int main() {
	vector<int> vec{ 1,2,3,4,5,6,7 };

	UnionFindSet ufset(vec);
	ufset.union_set(1, 2);
	ufset.union_set(1, 3);
	cout << "2的父亲是" << ufset.findhead(2) << endl;
	system("pause");
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值