并查集详解

并查集是一种树型数据结构,用于处理不相交集合的合并和查询。主要操作包括查找(Find)和合并(Union)。Find函数通过递归查找确定元素的最老祖先,而Union函数则通过从根修改法则和靠左法则合并两个集合。并查集在解决如亲戚关系查询等问题时,能有效避免深度搜索的复杂性。

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

并查集

并查集是一种很实用的算法,那么就让我们讲一讲并查集吧!

并查集的定义

1. 并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题。

2. 并查集通常包含两种操作

1)查找(Find):查询两个元素是否在同一个集合中

2)合并(Union):简称uni,就是把两个不相交的集合合并为一个集合

我们来做一道很好的练习题——亲戚

这道题其实我们可以用搜索,强力搜出两者是否有亲戚关系,可是这也太麻烦了,有没有什么更好的办法呢?

没错,就是并查集。

并查集其实就是一个模板,首先我们来看看find函数。

其中数组f代表了一个人的父节点,如果一个人的父节点是他自己,那么他就到终点了。

如果他还有父亲,那么我们就继续找他的父亲。

那么uni合并函数又是怎样的呢?更简单了:

就是将两个人的父节点变成一个。也就是说,我们找到了父节点,就找到了并查集的根本所在。

其实并查集就是将两个不同的树合并成一个,第一次合并,可能只有两个节点,可到后来就需要两个大树合并成一个超大树,这时我们只需要将其中一棵树的根节点指向另一棵树的根节点,也就是将一棵树放进另一棵树当中,就这么简单!

find

我们接下来先详细解释一下find函数什么意思,请看如下代码:

可能你看这段代码还不理解,那我们就拿一道题举例:亲戚

在题目中,我们每个亲戚的关系可以用搜索做,但是这样太麻烦了,我们就要用到并查集中的靠左法则。代码中的x是某一个亲戚,而我们知道,如果一个人的祖先是自己,那他就是最“老”的祖先(根节点),并查集就是利用这种树的关系。

f[x]就是代表一个人的祖先是谁,可是如果我们继续找祖先是否有祖先,发现这个祖先竟然还有祖先,那是不是说,x的祖先另有其人?我们f[x]里要存储的是一个人最“老”的祖先!这段代码是干什么的了呢?当我们要调查一个人的祖先时,就要调用find函数,如果发现它的祖先是自己,那么我们是不是就知道它就是最老的祖先了呢?这时候我们就返回他自己是最老的祖先。如果他的祖先不是自己,也就是他不是最老的祖先,那我们就找他的祖先是否有祖先,如果它的祖先没有祖先,也就是它的祖先是最老的,那么就停止。你发现了没有,这其实就是一个递归的过程,我们修改祖先也就是在回溯的时候,不影响时间复杂度,这时你就知道了吧,find函数就是用这样的原理来寻找并修改自己的祖先的。

union

uni函数包含了两个法则:从根修改法则靠左法则

首先我们来看看uni函数的核心代码:

find函数你已经知道是什么意思了,我们就来看看这是怎么合并的。

如果要将两个结点合并,其实比较简单,就是将一个结点的父节点指向另一个节点,两个树合并,就是要将他们的根结点如上合并,也很简单。我们知道了并查集其实就像一棵树。如果我们将给入的两个节点合并,那可能会使树很深,最后搜索答案麻烦。可是如果我们找到他们的根结点,将其中一棵树的根结点的父亲指向另一个根结点,相当于使一个树的根结点的子树增加,这样的话深度不变,搜索起来很方便,所以我们就要找到两者的最老祖先合并,也就是如上需要调用find函数的原因,而这一步就是从根修改法则的根本。

靠左法则什么意思呢?更简单,就是将y的最老祖先“认爹”,而这个新的父节点就是x的最老祖先,也就是说认爹祖先在左,父节点在右。

这就是find和uni的主要用途。那我们就拿亲戚这一题举例,看懂代码你就看懂了并查集。

是不是很直白明了!很简单吧!这就是神奇好玩的并查集!!

By ImNot6Dora

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值