一文搞懂并查集

2023-09-21 08:49:19

1 背景意义

首先要知道并查集可以解决什么问题呢?

  • 并查集常用来解决 连通性 问题。
  • 大白话就是当我们需要判断 两个元素 是否在 同一个集合 里的时候,我们就要想到用并查集

并查集主要有两个功能:

  • 两个元素 添加 到一个集合中;
  • 判断 两个元素 在不在 同一个集合。

接下来围绕并查集的这两个功能来展开讲解。

2 原理讲解

从代码层面,我们如何将两个元素 添加 到同一个集合中呢?

举个栗子:

我们将三个元素 ABC (分别是数字)放在同一个集合,其实就是将三个元素连通在一起,如何连通呢。

  • 只需要用一个 一维数组 来表示,即:father[A] = Bfather[B] = C 这样就表述 A BC连通了(有向连通图)。
  • A 连通 BA索引下标,根据 father[A] 的数值就知道 A 连通 B

⭐️ 添加元素代码如下:

// 将v,u 这条边加入并查集
void join(int u, int v) {
    u = find(u); // 寻找u的根
    v = find(v); // 寻找v的根
    if (u == v) return; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回
    father[v] = u;
}

那么 判断 这三个元素是否在同一个集合里?

  • 其实知道 A 连通 B 就已经足够了,也就是 寻根 思路,只要 ABC 在同一个根下就是同一个集合;
    • 给出 A 元素,就可以通过 father[A] = Bfather[B] = C,找到根为 C
    • 给出 B 元素,就可以通过 father[B] = C,找到根也为为 C,说明 AB 是在同一个集合里。

⭐️ find 函数代码如下:

// 并查集里寻根的过程
int find(int u) {
    if (u == father[u]) return u; // 如果根就是自己,直接返回
    else return find(father[u]); // 如果根不是自己,就根据数组下标一层一层向下找
}

如何表示 C 也在同一个元素里呢?

  • 我们需要 father[C] = C,即 C 的根也为 C,这样就方便表示 ABC 都在同一个集合里了。

⭐️ father数组初始化代码如下:

// 并查集初始化
void init() {
    for (int i = 0; i < n; ++i) {
        father[i] = i;
    }
}

最后我们如何 判断 两个元素是否在同一个集合里?

  • 如果通过 find函数 找到 两个元素属于同一个根 的话,那么这两个元素就是同一个集合,

⭐️ 判断 是否同根函数代码如下:

// 判断 u 和 v是否找到同一个根
bool isSame(int u, int v) {
    u = find(u);
    v = find(v);
    return u == v;
}

3 路径压缩

在实现 find 函数的过程中,我们知道,通过递归的方式,不断获取 father 数组下标对应的数值,最终找到这个集合的根。

  • 如果这棵多叉树高度很深的话,每次 find 函数 去寻找跟的过程就要递归很多次
  • 所以可以将 非根节点所有节点 直接指向 根节点
  • 递归的过程中,让 father[u] 接住 递归函数 find(father[u])返回结果

因为 find 函数向上寻找根节点father[u] 表述 u父节点,那么让 father[u] 直接获取 find函数 返回的 根节点,这样就让节点 u 的父节点 变成根节点

⭐️ 代码如下,注意看注释,路径压缩就一行代码:

// 并查集里寻根的过程
int find(int u) {
    if (u == father[u]) return u;
    else return father[u] = find(father[u]); // 路径压缩,如果没有找到父节点,会一直更新
}

以上代码在C++中,可以用三元表达式来精简一下,代码如下:

int find(int u) {
    return u == father[u] ? u : father[u] = find(father[u]);
}

4 代码模板

综上整理,模板如下

int n = 1005; // n根据题目中节点数量而定,一般比节点数量大一点就好
vector<int> father = vector<int> (n, 0); // C++里的一种数组结构

// 并查集初始化
void init() {
    for (int i = 0; i < n; ++i) {
        father[i] = i;
    }
}
// 并查集里寻根的过程
int find(int u) {
    return u == father[u] ? u : father[u] = find(father[u]); // 路径压缩
}

// 判断 u 和 v是否找到同一个根
bool isSame(int u, int v) {
    u = find(u);
    v = find(v);
    return u == v;
}

// 将v->u 这条边加入并查集
void join(int u, int v) {
    u = find(u); // 寻找u的根
    v = find(v); // 寻找v的根
    if (u == v) return ; // 如果发现根相同,则说明在一个集合,不用两个节点相连直接返回
    father[v] = u;
}

通过模板,我们可以知道,并查集主要有 三个功能

  1. 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个;
  2. 将两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上;
  3. 判断两个节点是否在同一个集合,函数:isSame(int u, int v),就是判断两个节点是不是同一个根节点。

注:仅供学习参考,如有不足,欢迎指正

更多推荐

MyBatis初级

文章目录一、mybatis1、概念2、JDBC缺点2.1、之前jdbc操作2.2、原始jdbc操作的分析3、mybatis的使用3.1、导入maven依赖3.2、新建表3.3、实体类3.4、编写mybatis的配置文件3.5、编写接口和映射文件3.6、编写测试类3.7、注意事项4、代理方式开发5、mybatis和spr

03MyBatis-Plus中的常用注解

常用注解@TableNameMyBatis-Plus根据BaseMapper中指定的泛型(实体类型名)确定数据库中操作的表,如果根据实体类型名找不到数据库中对应的表则会报表不存在异常//向表中插入一条数据@TestpublicvoidtestInsert(){Useruser=newUser(null,"张三",23,

华为云云耀云服务器L实例评测 | Linux系统宝塔运维部署H5游戏

文章目录前言一、云服务器相对传统服务器有什么优势1.1、可伸缩性(Scalability)1.2、灵活性(Flexibility)1.3、高可用性(HighAvailability)1.4、备份和恢复(BackupandRecovery)1.5、成本效益(Cost-Effectiveness)1.6、全球性(Globa

SpringMvc常用注解

目录一、@RequestParam二、@RequestHeader,@CookieValue三、@ModelAttribute(1)作用1(2)作用2四、@ResponseBody五、@RestController六、@RequestBody一、@RequestParam@RequestParam可以在控制器方法中获取

Java线程池ExecutorService和Executors应用(Spring Boot微服务)

记录:476场景:在SpringBoot微服务中使用ExecutorService管理Java线程池。使用Executors创建线程池。使用Runnable接口实现类提交线程任务到线程池执行。版本:JDK1.8,SpringBoot2.6.3。1.线程和线程池基础JDK自带线程和线程池包位置:java.util.con

嵌入的是PWM

PWM简介在嵌入式系统中,PWM(脉冲宽度调制)是一种常用的技术,用于控制和生成脉冲信号,通常用于控制电机、LED亮度、音频输出等。针对STM32微控制器,它们通常具有内置的PWM控制器模块,使PWM生成相对容易。PWM是一种用于控制电子设备的技术,通过调整信号的脉冲宽度和周期,可以模拟出不同的电压或功率级别。频率、占

JVM 虚拟机 ---->垃圾收集算法

文章目录JVM垃圾收集器一、判断对象是否存活1、引用计数算法(1)基本思路(2)存在的问题2、可达性分析算法(1)基本思路二、Java中的四种引用方式1、强引用(StrongReference)(1)弱化方式1(2)弱化方式22、软引用(SoftReference)3、弱引用(WeakReference)4、虚引用(P

外包干了2个月,技术退步明显.......

先说一下自己的情况,大专生,18年通过校招进入武汉某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试,已经让我变得不思进取,谈了2年的女朋友也因为我的心态和工资和我分手了。于是,我决定要改变现状,冲击下大厂。刚开始准备时

十五、垃圾回收相关算法

目录一、标记阶段:引用计算法对象存活判断引用计算法二、标记阶段:可达性分析算法三、对象的finalization机制四、MAT和Jprofiler的GCToots的溯源五、垃圾清除算法之标记-清除算法六、垃圾清除算法之复制算法七、垃圾清除算法之标记-压缩算法八、小结分代收集算法九、增量收集算法、分区算法1、什么是增量收

【EI会议信息】第五届物联网、自动化和人工智能国际会议(IoTAAI 2023)

第五届物联网、自动化和人工智能国际会议(IoTAAI2023)20235thInternationalConferenceonInternetofThings,AutomationandArtificialIntelligence第五届物联网、自动化和人工智能国际会议(IoTAAI2023)将于2023年11月24-2

你的服务器还安全吗?用户数据是否面临泄露风险?

一系列严重的网络安全事件引起了广泛关注,多家知名公司的服务器遭到黑客挟持,用户的个人数据和敏感信息面临泄露的风险。这些事件揭示了网络安全的脆弱性和黑客攻击的威胁性,提醒着企业和个人加强对网络安全的重视。一、入侵案例1.1蔚来数据泄露1.2特斯拉、波音、SpaceX供应商拒付赎金遭机密泄露二、入侵常见方式2.1弱密码攻击

热文推荐