并查集——(一)概述

7 篇文章 0 订阅

并查集概念

在计算机科学中,并查集是一种树型的数据结构,用于处理一些不交集(Disjoint Sets)的合并及查询问题。

并查集数据结构表示

常用的并查集实现有两种方法。

使用数组

我们使用数组来表示这样的数据结构。

比如,我们知道这个集合最大元素个数为 10^5 个,也就是 1 ~ 10^5。那么我们可以定义一个数组来记录每个元素的父节点。

const int MAXN=1e5+4;
int parent[MAXN];
memset(parent, -1, sizeof(parent));

如上定义,元素 i 的父节点保存在对应的 parent[i] 中。例如:

parent[i]=-1,表示节点 i 没有父节点。

parent[3]=5,表示节点 3 的父节点为 5。我们拥有的集合如图所示,

parent[1]=7,表示节点 1 的父节点为 7。我们拥有的集合如图所示,

parent[7]=5,表示节点 7 的父节点为 5。我们拥有的集合如图所示,

使用 STL 的 map 来实现

数组的问题是数组下标不能为负数。当我们元素出现负数的时候,使用 map 更加方便。

map<int, int> ds;

这样就可以表示一个并查集。含义和数组定义并查集是一样的。

并查集操作

并查集的操作主要有两个。查集和并集。

查集

主要作用是查询两个集合是否相交。比如,我们有两个集合 {A} 和 {B},集合 {A} 中有元素 x,集合 {B} 中有元素 y。find_root() 用来查询集合 {A} 和集合 {B} 是否相交。

int x_root=find_root(x);
int y_root=find_root(y);
if (x_root==y_root) {
    集合相交
} else {
    集合不相交
}

并集

主要作用是将两个集合是否合并成为一个新的集合。比如,我们将元素 x 的父亲设置为 y,则就将这两个元素变成一个新的集合。

int x_root=find_root(x);
int y_root=find_root(y);
if (x_root!=y_root) {
    parent[x]=y;
}

并查集举例

元素从 1 ~ 8。我们用数组 parent[9] 来表示。

初始状态

图形表示为,这样,我们有 8 个独立的集合。

对应的 parent 数组值为

parent[1]=-1;
parent[2]=-1;
parent[3]=-1;
parent[4]=-1;
parent[5]=-1;
parent[6]=-1;
parent[7]=-1;
parent[8]=-1;

这样表示,每个元素的父节点都是自己,也就是每个元素都是独立的集合。

合并 3 和 4

集合的图像变为

对应的 parent 数组值为

parent[1]=-1;
parent[2]=-1;
parent[3]=4;
parent[4]=-1;
parent[5]=-1;
parent[6]=-1;
parent[7]=-1;
parent[8]=-1;

我们将元素 3 的父节点指向 4,这样 3 和 4 就在同一个集合中。

合并 1 和 2

集合的图像变为

对应的 parent 数组值为

parent[1]=2;
parent[2]=-1;
parent[3]=4;
parent[4]=-1;
parent[5]=-1;
parent[6]=-1;
parent[7]=-1;
parent[8]=-1;

我们将元素 1 的父节点指向 2,这样 1 和 2 就在同一个集合中。

查询 1 和 5 是否在同一个集合

通过查询,我们知道元素 1 的父节点是 2,元素 5 的父节点是 5。这样说明 1 和 5 不在同一集合。

查询 3 和 4 是否在同一个集合

通过查询,我们知道元素 3 的父节点是 4,元素 4 的父节点是 4。这样说明 3 和 4 在同一集合。

合并 1 和 3

集合的图像变为

我们查询元素 1 的父节点,得到 2;查询元素 3 的父节点,得到 4。对应的 parent 数组值为

parent[1]=2;
parent[2]=4;
parent[3]=4;
parent[4]=-1;
parent[5]=-1;
parent[6]=-1;
parent[7]=-1;
parent[8]=-1;

合并 5 和 8

集合的图像变为

对应的 parent 数组值为

parent[1]=2;
parent[2]=4;
parent[3]=4;
parent[4]=-1;
parent[5]=8;
parent[6]=-1;
parent[7]=-1;
parent[8]=-1;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

努力的老周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值