文章目录
- 前言
- 一、并查集
- 1、并查集原理
- 2、并查集实现
- 3、并查集应用
- 1.省份数量
- 2.等式方程的可满足性
前言
一、并查集
1、并查集原理
在一些应用问题中,需要将n个不同的元素划分成一些不相交的集合。开始时,每个元素自成一个单元素集合,然后按一定的规律将归于同一组元素的集合合并。在此过程中要反复用到查询某一个元素归属于那个集合的运算。适合于描述这类问题的抽象数据类型称为并查集(union-find set)。
例如某公司今年校招共招10个人,北京招4人,河南招3人,西安招3人,10个人来自不同的学校,刚开始互相都不认识,所以每个人都是一个独立的小团体,我们给这些人进行编号:{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};然后我们使用下面的数组来存储该小集合。数组中存的-1中的1表示现在每个团体中都只有1个人,负号表示这个人就是这个团体的根结点。
毕业后,学生们要去公司上班,每个地方的学生自发组织成小队一起上路,于是北京学生小分队S1={0, 6, 7, 8},河南小分队S2={1, 4, 9},西安小分队S3={2, 3, 5},这时10个人就形成了3个小团体。假设三个队长由0,1,2担任。下面为集合的树形表示。
下面为S1、S2、S3集合使用数组表示。可以看到北京的队长为0,所以数组中下标为0的空间中存储了-4,4表示S1这个集合有4个人,负号表示编号为0的同学是树的根结点,即队长。而数组中下标为6,7,8的空间中存了0,这存储的是6,7,8的父结点的下标0,即表示编号为6,7,8的同学的队长为0。S2和S3集合在数组中的存储也同理。
仔细观察数组,可以得出以下结论:
- 数组的下标对应集合中元素的编号。
- 数组中如果为负数,负号代表根,数字代表该集合中元素个数。
- 数组中如果为非负数,代表该元素双亲在数组中的下标。
在公司工作一段时间后,北京小分队中8号同学与河南小分队1号同学奇迹般的走到了一起,两个小圈子的学生相互介绍,最后成为了一个小圈子。此时就相当于S1和S2集合合并了,下面为合并后集合的树形表示。
下面为集合在数组中的表示。现在0集合有7个人,2集合有3个人,总共两个朋友圈。
通过以上例子可知,并查集一般可以解决一下问题:
- 查找元素属于哪个集合
沿着数组表示树形关系向上一直找到根。(即:树中元素为负数的位置) - 查看两个元素是否属于同一个集合
沿着数组表示的树形关系向上一直找到树的根,如果根相同表明在同一个集合,否则不在。 - 将两个集合归并成一个集合
将两个集合中的元素合并。
将一个集合名称改成另一个集合的名称。 - 集合的个数
遍历数组,数组中元素为负数的个数即为集合的个数。
2、并查集实现
下面我们来简单实现一个并查集。
下面实现返回元素根结点的函数。
下面再来实现合并集合的函数。
下面再来实现判断两个元素在同一集合,查看集合数的函数。这样我们就实现了一个简单的并查集。
3、并查集应用
1.省份数量
题目链接:省份数量
这个题目我们可以使用并查集来解决,即相连的城市就表示在同一个集合,这样最后只需要知道并查集中有多少集合,就知道了省份的数量。我们先将上面实现的并查集放到题目中。
然后我们创建一个并查集,遍历矩阵,并且将相连的城市作为同一个集合,进行合并。
上面我们使用到了一个并查集,那么写这个题之前就需要实现一个并查集,这样是很麻烦的,所以下面我们不使用并查集来做这一题。
2.等式方程的可满足性
题目链接:等式方程的可满足性
这个题目我们也可以使用并查集的思想来实现,我们可以创建一个可以存26个元素的数组,然后我们可以先遍历一遍数组,将相等的值放到一个集合里面,然后再遍历一遍数组,查看不相等的字符串,如果不相等的字符串也在同一个集合,那么这就是相悖的。