并查集的原理及实现

时间:2022-07-24
本文章向大家介绍并查集的原理及实现,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

并查集原理

在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合,然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一个元素归属于那个集合的运算。适合于描述这类问题的抽象数据类型称为并查集(union-findset)。 并查集一般可以解决一下问题:

  1. 查找元素属于哪个集合 沿着数组表示树形关系以上一直找到根(即:树中中元素为负数的位置)
  2. 查看两个元素是否属于同一个集合 沿着数组表示的树形关系往上一直找到树的根,如果根相同表明在同一个集合,否则不在
  3. 将两个集合归并成一个集合 将两个集合中的元素合并 将一个集合名称改成另一个集合的名称
  4. 集合的个数 遍历数组,数组中元素为负数的个数即为集合的个数。

并查集实现

#include<iostream>
#include<vector>
using namespace std;

class UnionFindSet{
public:
	UnionFindSet(size_t size)//构造函数,初始化数组大小
	:_a(size,-1){
	}
	int FindRoot(int x){//查找根节点
		while (_a[x] >= 0){//循环寻找节点小于0的节点为根
			x = _a[x];
		}
		return x;
	}
	bool Union(int x1, int x2){//合并两个节点
		int root1 = FindRoot(x1);//查找两个节点的根节点
		int root2 = FindRoot(x2);
		if (root1 == root2)//根节点相同,说明在一根树上
			return false;
		_a[root1] += _a[root2];//将root1根节点的值变为root2的值和root1值的和,也就是负的子节点个数
		_a[root2] = root1;//将root2的值赋予root1节点中
		return true;
	}
	size_t Count(){//根节点的个数,即节点值小于0的个数
		int count = 0;
		for (auto e : _a){
			if (e < 0)
				count++;
		}
		return count;
	}
private:
	vector<int> _a;
};