【数据结构】并查集的简单实现,合并,查找(C++)

文章目录


前言

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

举例:

学生小分队s1={0,6,7,8},成都学生小分队s2={1,4,9},武汉学生小分队s3={2,3,5}就相互认识了,10个人形成了三个小团体。假设右三个群主0,1,2担任队长,负责大家的出行。

西安小分队中8号同学与成都小分队1号同学奇迹般的走到了一起,两个

小圈子的学生相互介绍,最后成为了一个小圈子:

仔细观察数组中内融化,可以得出以下结论:

  1. 数组的下标对应集合中元素的编号
  2. 数组中如果为负数,负号代表根,数字代表该集合中元素个数
  3. 数组中如果为非负数,代表该元素双亲在数组中的下标

一、

1.构造函数

cpp 复制代码
UnionFindSet(size_t size)
		:_set(size,-1)//数组中初始化为-1
		//数组的下标对应集合中元素的编号
		//数组的内容如果是非负数代表这个元素的根的下标
		//数组内容为负数,代表这个数字为根,绝对值为这棵树的大小
		{}

2.查找元素属于哪个集合FindRoot

cpp 复制代码
size_t FindRoot(int x) {//. 查找元素属于哪个集合
			while (_set[x] >= 0) {
				x = _set[x];
			}
			//找到非负的数,这个数的下标即为根的下标
			return x;
		}

3.将两个集合归并成一个集合Union

cpp 复制代码
void Union(int x1, int x2) {//将两个集合归并同一个集合
			//将元素x2合并进x1
			int root1 = FindRoot(x1);
			int root2 = FindRoot(x2);
			if (root1 != root2) {//保证两个元素不在同一个集合中
				_set[root1] += _set[root2];
				// x2根的内容为负数绝对值为这棵树的数量
				//把x2归并到x1所在集合中
				//x1所在集合的大小发生变化
				_set[root2] = root1;
				//x2的根发生变化
			}
		}

4.查找集合数量SetCount

cpp 复制代码
size_t SetCount() {//统计集合数量(有多少棵树)
			int count = 0;
			for (size_t i = 0; i < _set.size(); i++) {
				if (_set[i] < 0) {
					count++;
				}
			}
			//负数的数量即根的数量即集合的数量
			return count;

		}

5.是否在同一个集合中

cpp 复制代码
bool InSet(int x1, int x2)
	{
		return FindRoot(x1) == FindRoot(x2);
	}

二、源码

cpp 复制代码
class UnionFindSet {
public:
		UnionFindSet(size_t size)
			:_set(size,-1)//数组中初始化为-1
			//数组的下标对应集合中元素的编号
			//数组的内容如果是非负数代表这个元素的根的下标
			//数组内容为负数,代表这个数字为根,绝对值为这棵树的大小
		{}

		size_t FindRoot(int x) {//. 查找元素属于哪个集合
			while (_set[x] >=0) {
				x = _set[x];
			}
			//找到非负的数,这个数的下标即为根的下标
			return x;
		}
bool InSet(int x1, int x2)
{
return FindRoot(x1) ==  FindRoot(x2);
	}
		void Union(int x1, int x2) {//将两个集合归并同一个集合
			//将元素x2合并进x1
			int root1 = FindRoot(x1);
			int root2 = FindRoot(x2);
			if (root1 != root2) {//保证两个元素不在同一个集合中
				_set[root1] += _set[root2];
				// x2根的内容为负数绝对值为这棵树的数量
				//把x2归并到x1所在集合中
				//x1所在集合的大小发生变化
				_set[root2] = root1;
				//x2的根发生变化
			}
		}

		size_t SetCount() {//统计集合数量(有多少棵树)
			int count = 0;
			for (size_t i = 0; i < _set.size(); i++) {
				if (_set[i] < 0) {
					count++;
				}
			}
			//负数的数量即根的数量即集合的数量
			return count;

		}

private:
	vector<int> _set;
 };
相关推荐
宁静致远202116 分钟前
Ubuntu下的Doxygen+VScode实现C/C++接口文档自动生成
c++·vscode·ubuntu
Bluesonli21 分钟前
第 2 天:创建你的第一个 UE5 C++ 项目!
c++·学习·ue5·虚幻·虚幻引擎·unreal engine
taopi202441 分钟前
android java系统弹窗的基础模板
android·java·开发语言
比特在路上43 分钟前
蓝桥杯之c++入门(四)【循环】
c++·职场和发展·蓝桥杯
pay顿1 小时前
C++基础day1
c++·学习·笔试
孤寂码农_defector1 小时前
C++【iostream】数据库的部分函数功能介绍
c++
松仔log1 小时前
Java多线程——对象的组合
java·开发语言·jvm
qq_433618441 小时前
哈夫曼树
数据结构·算法
Icomi_1 小时前
【PyTorch】7.自动微分模块:开启神经网络 “进化之门” 的魔法钥匙
c语言·c++·人工智能·pytorch·python·机器学习·计算机视觉
余辉zmh1 小时前
【贪心算法篇】:“贪心”之旅--算法练习题中的智慧与策略(二)
c++·算法·leetcode·贪心算法