首页 > 其他分享 >并查集详解

并查集详解

时间:2024-07-29 20:55:16浏览次数:13  
标签:查集 int 元素 节点 详解 集合 find

一、概念

1.定义:并查集 (英文:Disjoint-set data structure,直译为不交集 数据结构 )是一种数据结构,用于处理一些不交集(Disjoint sets,一系列没有重复元素的集合)的合并及查询问题

2.功能:并查集主要有两个功能。

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

3.作用:并查集经常用来解决连通性问题。就是给你几组数据,他们之间存在一定关系,根据这种关系能否从一个元素到达另外一个元素。

4.主要构成:并查集主要由一个整型数组f[ ]和两个函数find( )、join( )构成。

数组 f[ ] 记录了每个点的父亲 (father) 节点是谁,函数 find(x) 用于查找指定节点 x 属于哪个集合,函数 merge(x,y) 用于合并两个节点 x 和 y 。

作用:

二、原理

当题目给你许多组数据的时候,问你谁和谁是同类。这时候我们便需要分类讨论,将同类分到一个集合中,但是这样的集合可能不止一个,也许有很多集合,所以我们需要将他们分为许多个数组存储。但是这样下来,当我们再回头去查找一个元素是哪个集合元素的同类或者添加一个新元素在它的同类集合中的时候,我们是不是需要每次都遍历一遍新建的全部数组(当然也有可能运气好一次就找到,但是我估计没人能次次碰对),这样大大增加了时间的效率,所以我们就想出来一个方法叫并查集,这样可以提高代码的时间复杂度。从这我们引出一维数组f[ ]。

比如说:我们有三个元素5,2,1它们的关系为:5->2,2->1那么我们只需要用一个一维数组来表示,即:f[5] = 2,f[2] = 1 这样就表述 5与 2 与 1连通了(有向连通图)。如果还有其他元素不在这个集合中,也可以直接添加进去:eg:f[6]=7;这些元素都可以添加进去到时候使用它们的父亲节点来查询他们是否为连通的(即是否为同类元素)。

三、merge()函数的定义和实现

1.定义:如果两个元素是连通的,则合并两个元素到一个集合中。

2.实现

void merge(int x, int y)
{
	int fx = find(x);//查找x元素的根节点
	int fy = find(y);//查找y元素的根节点
//如果发现两个元素根节点不同,直接让x的根节点指向y的根节点,这样两个元素就可以连通了。
	if (fx != fy)
		f[fx] = fy;
}

四、find()函数定义和实现

1.定义:举个例子:

给出5元素,就可以通过 f[5] = 2,f[2] = 1,找到根为 1。

给出2元素,就可以通过 f[2] = 1,找到根也为1,说明 5 和 2 是在同一个集合里。这样我们就能知道这个find函数就是用来寻找两个元素的根的一个函数。其实就是通过数组下标找到数组元素,一层一层寻根过程,代码如下:

//非递归方法
int find(int x)					
{
	while(f[x] != x)			
		x = f[x];				
	return x;				
}


递归方法
int find(int x) {
    if (x == f[x]) return x; // 如果根就是自己,直接返回
    else return find(f[x]); // 如果根不是自己,就根据数组下标一层一层向下找
}

五、路径压缩算法

我们这个并查集是一个树形结构,所以时间就消耗在遍历树的元素上,遍历树的元素时间大小跟树的高度有关,如果树的高度很大,那么查找路径就很长,当查找量很大的时候就容易TLE。

解决方案:找到根节点,修改查找路径上的所有节点,将他们都指向根节点。如图所示:

2.代码实现

int find(int x) {
    if (x == f[x]) return x;
    else return f[x] = find(f[x]); // 路径压缩
}

六、模板

并查集对应着三种操作,初始化,查找和合并,这三种函数的模板总结如下所示

vector<int> f(1001);
//初始化f[]数组
//这个初始化函数可以直接写在主函数中(我一般直接写的)
void init()
{
	for (int i = 0; i < n; i++)
	{
		f[i] = i;
	}
}
//查找
int find(int x) {
	if (x == f[x]) return x;
	else return f[x] = find(f[x]); // 路径压缩
}

//合并
void merge(int x, int y)
{
	int fx = find(x);
	int fy = find(y);
	if (fx != fy)
		f[fx] = fy;
}

七、总结

本章就讲解了并查集的原理和做法,有不足的地方欢迎指正谢谢。最后我也推荐两道题赶紧去做做吧,稍后我会发布解题方法放在我的并查集专栏中,欢迎观赏!

八、练习题

1.冗余连接

2.岛屿数量


 

标签:查集,int,元素,节点,详解,集合,find
From: https://blog.csdn.net/weixin_73392207/article/details/140778819

相关文章

  • MySQL数据库基础操作与概念详解(三)
    DML和DQL语句1.新增–INSERTINTO表名(字段名,字段名,…字段名)values/value(值,值,…值)–日期使用字符串的形式进行书写日期格式(yyyy-MM-ddHH-dd)1.全字段的输入(1)方式一INSERTINTOstudent(sid,sname,birthday,ssex,classid)VALUES(9,‘张三’,‘2002-9-23’,‘......
  • MySQL数据库基础操作与概念详解(二)
    二、数据库的操作1.--表结构修改–ALTERTABLE表名关键词数据;–ALTERTABLE旧表名renameas新表名;修改表名例:ALTERTABLEstudentrenameasstudents;SHOWTABLES;2.–添加字段ALTERTABLE表名ADD新字段名类型属性;ALTERTABLEstudentsADDstu_......
  • 小一保姆级 python三大核心多态、抽象类、动态添加内容详解
    一.多态多态是面向对象编程中的一个核心概念,它允许一个接口被多个数据类型实现。这意味着,即使多个类具有不同的内部实现,它们也可以共享一个公共接口。多态的实现通常依赖于继承和方法重写。继承:子类继承父类的属性和方法。方法重写:子类重写父类中的方法,以提供特定的实现。......
  • Java 启动参数最全详解
    Java启动参数最全详解!在Java开发中,发布JAR文件是一个常见的操作。合理设置启动参数可以确保应用程序在不同环境中正常运行,并优化性能。本文将详细介绍所有可能的启动参数,以及它们的使用场景、设置建议和具体示例。一、JAR文件基础JAR(JavaArchive)文件用于打包Java......
  • Linux操作系统下编译、链接过程详解
    gcc和g++的区别:gcc和g++是GNU编译器集合中的两个不同的编译器,它们之间的主要区别在于它们所针对的编程语言以及它们的行为和功能。1.编译器的目标语言:gcc是用于编译C语言的编译器,而g++是用于编译C++语言的编译器。因此它们分别用于编译不同的源代码文件;2.语法支持:gcc和......
  • TCP协议详解
    TCP协议详解TCP(TransmissionControlProtocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它在网络通信中扮演着至关重要的角色,尤其是在需要保证数据完整性和顺序性的应用场景中。以下是对TCP协议的详细解析,包括其工作原理、特点、应用场合以及关......
  • AI大模型Prompt提示词工程使用详解
    AI大模型Prompt提示词工程使用详解在人工智能(AI)的浩瀚宇宙中,大型预训练模型(LargeLanguageModels,LLMs)如GPT系列、BERT等,以其卓越的自然语言处理(NLP)能力,正逐步改变着人类与机器交互的方式。这些模型不仅能够理解和生成人类语言,还能在多种任务上展现出惊人的创造力和适应......
  • rsync命令详解
     rsync命令是Linux和其他Unix-like系统上一个非常强大的命令行工具,主要用于数据同步和文件传输。它的名字是"remotesync"的缩写,但不仅限于远程同步,也支持本地文件和目录之间的同步。rsync的主要优势在于其高效的增量传输方式,即只传输源和目标之间发生变化的文件块,而不是整个文......
  • SoC片上系统详解
    在当今这个科技日新月异的时代,SoC(SystemonChip,系统级芯片或片上系统)作为集成电路技术的巅峰之作,正逐步渗透到我们生活的方方面面。从智能手机到智能家居,从工业控制到物联网设备,SoC以其独特的技术优势和广泛的应用场景,引领着科技潮流,推动着社会进步。本文将从技术角度深入剖析SoC......
  • Elasticsearch——聚合详解
    作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬学习必须往深处挖,挖的越深,基础越扎实!阶段1、深入多线程阶段2、深入多线程设计模式阶段3、深入juc源码解析阶段4、深入jdk其余源码解析......