实用数据结构【并查集】 - 原理

news2024/11/19 2:33:24

实用数据结构【并查集】 - 原理

[一个问题]

若某个部落过于庞大,则部落成员见面也有可能不认识。

已知某个部落的成员关系图,任意给出其中两个人,判断是否有亲戚关系。规定:①若x、y 是亲戚,y 和z 是亲戚,则x 和z 也是亲戚;②若x、y是亲戚,则x 的亲戚也是y 的亲戚,y 的亲戚也是x 的亲戚。

如何才能快速判断两个人是否有亲戚关系呢?

以上规定中的第①条是传递关系,第②条相当于两个集合的合并,因此对该问题可以采用并查集轻松解决。

并查集是一种树形数据结构,用于处理集合的合并查询问题。

【算法步骤】

① 初始化。

将每个节点所在的集合号都初始化为其自身编号。

② 查找。

查找两个元素所在的集合,即找祖宗。查找时,采用递归的方法找其祖宗,找到祖宗(集合号等于自身)时停止;然后回归,回归时将祖宗到当前节点路径上的所有节点都统一为祖宗的集合号。

③ 若两个节点的集合号不同,则将两个节点合并为一个集合,合并时只需将一个节点的祖宗集合号修改为另一个节点的祖宗集合号。擒贼先擒王,只改祖宗即可!

【举个栗子】

假设现在有7个人,首先输入亲戚关系图,然后判断两个人是否有亲戚关系。

① 初始化

在这里插入图片描述

② 查找。

输入亲戚关系2、7,查找到2的集合号为2,7的集合号为7。

③ 合并。

两个元素的集合号不同,将两个元素合并为一个集合。在此约定将小的集合号赋值给大的集合号, 因此修改fa[7]=2。

在这里插入图片描述

④ 查找。

输入亲戚关系4、5,查找到4的集合号为4,5的集合号为5。

⑤ 合并。两个元素的集合号不同,将两个元素合并为一个集合,修改fa[5]=4。

在这里插入图片描述

⑥ 查找。输入亲戚关系3、7,查找到3的集合号为3,7的集合号为2。

⑦ 合并。两个元素的集合号不同,将两个元素合并为一个集合,修改fa[3]=2。

在这里插入图片描述

⑧ 查找。输入亲戚关系4、7,查找到4的集合号为4,7的集合号为2。

⑨ 合并。两个元素的集合号不同,将两个元素合并为一个集合,修改fa[4]=2。

在这里插入图片描述

擒贼先擒王,只改祖宗即可!有两个节点的集合号为4,只需修改两个节点中的祖宗,无须将集合号为4的所有节点都检索一遍,这正是并查集的巧妙之处!

⑩ 查找。输入亲戚关系3、4,查找到3的集合号为2,4的集合号为2。

⑪ 合并。两个元素的集合号相同,无须合并。

⑫ 查找。输入亲戚关系5、7,查找到7的集合号为2,查找到5的集合号不等于5,所以找5的祖宗。首先找到其父节点4,4的父节点为2,2的集合号等于2(祖宗),搜索停止。返回时,将祖宗到当前节点路径上所有节点的集合号都统一为祖宗的集合号。更新5的集合号为祖宗的集合号2。

在这里插入图片描述

⑬ 合并。两个元素的集合号相同,无须合并。

⑭ 查找。输入亲戚关系5、6,查找到5的集合号为2,6的集合号为6。

⑮ 合并。两个元素的集合号不同,将两个元素合并为一个集合,修改fa[6]=2。

在这里插入图片描述

⑯ 查找。输入亲戚关系2、3,查找到2的集合号为2,3的集合号为2。

⑰ 合并。两个元素的集合号相同,无须合并。

⑱ 查找。输入亲戚关系1、2,查找到1的集合号为1,2的集合号为2。两个元素的集合号不同,将两个元素合并为一个集合,修改fa[2]=1。

在这里插入图片描述

OK。假设到此为止,亲戚关系图已经输入完毕。可以看到3、4、5、6、7这些节点的集合号并没有被修改为1,这样做真的可以吗?

现在,判断5和2是不是亲戚关系,则过程如下。

① 查找到5的集合号为2,5的集合号不等于5,找其祖宗。首先查找到5的父节点2,2的父节点1,1的集合号为1(祖宗),搜索停止。将祖宗1到5这条路径上所有节点的集合号都更新为1。

② 查找到2的集合号为1,找其祖宗。2的祖宗为1,1的集合号为1(祖宗),搜索停止。将祖宗1到2这条路径上所有节点的集合号都更新为1。

③ 5和2的集合号都为1,因此5和2是亲戚关系。

【算法实现】

① 初始化。将节点i 的集合号初始化为其自身编号。

void init(){ //初始化集合号
	for(int i = 1; i <= n ; i ++){
		fa[i] = i; //把节点i 的集合号初始化为其 自身编号
	}
}

② 查找。查找两个元素所在的集合,即找祖宗。查找时,采用递归的方法找其祖宗(集合号等于自身)。回归时,将祖宗到当前节点路径上的所有节点都统一为祖宗的集合号。

void Find(int x){ //查找
	if(x != fa[x]){
		fa[x] = Find(fa[x]);	
	}
	return fa[x];
}

fa[x ]表示x 的集合号,若x !=fa[x ],则说明x 节点不是祖宗。继续向上找,找到祖宗后返回。回归时将祖宗到当前节点路径上的所有节点都统一为祖宗的集合号,如下图所示。

在这里插入图片描述

③ 合并。先找到x 的集合号a ,y 的集合号b ,若a 和b 相等,则无须合并。若a 和b 不相等,则将a 的集合号修改为b ,或者将b 的集合号修改为a 。擒贼先擒王,只改祖宗即可

void Union(int x, int y){ //合并
	int a = Find(x);
	int b = Find(y);
	
	if(a != b){
		fa[b] = a;
	}
}

输入1和8的亲戚关系,先找到1的祖宗2,8的祖宗6,将6的集合号修改为2即可。

在这里插入图片描述

【算法分析】

若有n 个节点、e 条边(关系),则每条边(u , v )进行集合合并时,都要查找u 和v 的祖宗,查找的路径为从当前节点一直到根节点,n 个节点组成的树的平均高度为logn ,因此并查集中,合并集合的时间复杂度为O (e logn )。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/11261.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】string的模拟实现

目录 一、std::swap和std::string::swap的区别 二、string的默认构造函数 1、构造函数 2、拷贝构造 3、赋值运算符重载 4、析构函数 三、string中的小接口 四、遍历接口的实现 1、对operator[]进行重载 2、迭代器 五、reserve和resize 六、插入删除查找相关接口 1…

DirtyCow脏牛漏洞复现(CVE-2016-5195)

DirtyCow脏牛漏洞复现 本文以vulnhub靶场中的lampiao为例复现脏牛提权漏洞 扫描c段 nmap -sS -Pn 192.168.1.0/24找到疑似ip 对该ip端口进行扫描&#xff0c;多扫出个1898端口 nmap -A -sV -p- 192.168.1.13访问80端口&#xff0c;没有有用的信息 1898也是个apche的http服务…

立足小餐饮,“新名酒”江小白能走多远?

&#xff08;图片来源于网络&#xff0c;侵删&#xff09; 来源 | 螳螂观察 文 | 叶小安 白酒市场从不缺新故事&#xff0c;但一直缺年轻人喜欢的白酒。 上月底&#xff0c;江小白旗下江记酒庄获重庆市江津区华信集团10亿元战略投资。与此同时&#xff0c;江小白产品理念升…

技术贴 | Rocksdb 中 Memtable 源码解析

一、什么是 Memtable&#xff1f; Memtable 是 Rocksdb 在内存中保存数据的一种数据结构&#xff0c;一个 Memtable 的容量是固定的&#xff0c;在 Memtable 写满后&#xff0c;会转换为 Immutable Memtable&#xff0c;Immutable Memtable 中的数据会 Flush 到 SST File 中。…

编程中老生常谈的【编码规范】你还记得多少?进来回顾一下吧【文末送书】

&#x1f3ac; 博客主页&#xff1a;https://xiaoy.blog.csdn.net &#x1f3a5; 本文由 呆呆敲代码的小Y 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f384; 学习专栏推荐&#xff1a;Unity精品学习专栏 &#x1f332; 游戏制作专栏推荐&#xff1a;游戏制作分享 &…

【genius_platform软件平台开发】第八十一讲:ARM Neon指令集一(ARM NEON Intrinsics, SIMD运算, 优化心得)

1. ARM Neon Intrinsics 编程 1.入门&#xff1a;基本能上手写Intrinsics 1.1 Neon介绍、简明案例与编程惯例 1.2 如何检索Intrinsics 1.3 优化效果案例 1.4 如何在Android应用Neon 2. 进阶&#xff1a;注意细节处理&#xff0c;学习常用算子的实现 2.1 与Neon相关的ARM体系结…

寻 友 软 件

寻友软件项目技术技术功能部署Redis部署RocketMQJWT&#xff08;Json Web Token&#xff09;虹软人脸识别部署MongoDB&#xff08;尽量不用docker部署mongo&#xff09;部署Nginx过滤器及拦截器加缓存编码流程DOC接口文档bug技术 技术 前端&#xff1a; flutterandroid环信S…

分销微信小程序介绍_分销小程序有什么作用呢

不同的微商城系统对于分销功能的支持会有不要的叫法&#xff0c;一般来说主要有两种&#xff0c;一种是基于商品分享的分销方式&#xff0c;通过分享链接识别客户从属关系&#xff0c;订单完成&#xff0c;结算佣金&#xff1b;另一种分销商可以建立并独立运营一个分销店铺&…

【JavaSE】关于多态那些事儿

目录 1. 多态 1.1 多态的概念 1.2 多态实现条件 1.3 向上转型 1.3.1 直接赋值 1.3.2 方法传参 1.3.3 方法返回 1.3.4 向上转型的优缺点 1.4 重写 1.4.1 重写的条件 1.4.2 重写注意事项 1.4.3 重载与重写的区别 1.5 通过父类的引用&#xff0c;调用这个父类和子类重…

CSS篇十六——盒子模型之边框

目录一、CSS盒子模型1.1 盒子模型组成1.2 边框&#xff08;border&#xff09;1.2.1 语法格式1.2.2 边框样式 border-style1.2.3 代码示例1.3 表格的细线边框1.3.1 语法格式、代码示例及结果一、CSS盒子模型 网页布局过程&#xff1a; 1.先准备好相关的网页元素&#xff0c;网…

My sql的深度剖析

一.数据库的创建、删除、使用 数据库的创建&#xff1a;create database 数据库名 数据库的删除&#xff1a;drop database 数据库名&#xff1b; 数据库的使用&#xff1a;use数据名&#xff1b; 所有数据库的查看&#xff1a;show databases; 建立数据时如何指定字符集…

在Java中计算Levenshtein莱文斯坦(相似度)编辑距离

在本教程中&#xff0c;我们将研究 Levenshtein 距离算法&#xff0c;该算法也称为编辑距离算法&#xff0c;用于比较单词的相似性。 什么是列文施泰因距离 Levenshtein距离算法由俄罗斯科学家Vladimir Levenshtein创建。 Levenshtein 距离算法通过计算将一个字符串转换为另…

基于单片机的贪吃蛇设计

1 绪论 1.1 设计目的 在21世纪的今天&#xff0c;人们的生活开始变得更加丰富多彩。在繁忙的工作之余&#xff0c;娱乐成为人们生活不可或缺的一份子&#xff0c;而游戏作为近年来逐渐兴起的一种娱乐方式&#xff0c;已经越来越受到人们的青睐。在工作学习之余&#…

dreamweaver网页设计作业制作 学生NBA篮球网页 WEB静态网页作业模板 大学生校园篮球网页代码 dw个人网页作业成品

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

第五章:双指针与离散化的映射

第五章&#xff1a;双指针、离散化、二进制运算与区间合并一、双指针1、什么是双指针&#xff1f;2、双指针的模板3、双指针例题&#xff08;1&#xff09;思路&#xff1a;&#xff08;2&#xff09;解答&#xff1a;C版&#xff1a;C版&#xff1a;二、离散化1、什么是离散化…

java面试强基(3)

重载和重写的区别? 重载 发生在同一个类中&#xff0c;方法名必须相同&#xff0c;参数类型不同、个数不同、顺序不同&#xff0c;方法返回值和访问修饰符可以不同。 重载就是同一个类中多个同名方法根据不同的传参来执行不同的逻辑处理。 重写 重写发生在运行期&#xff0c;…

go语言基本环境搭建

下载地址 Go官网下载地址&#xff1a;https://studygolang.com/dl 一、下载对应电脑得安装包 二、下载完成点击安装下一步&#xff08;选择目录尽量简单&#xff09; 三、是否安装成功 四、环境变量 GOROOT和GOPATH都是环境变量&#xff0c;其中GOROOT是我们安装go开发包的路…

【计算机毕业设计】Springboot医疗管理系统源码

一、系统截图&#xff08;需要演示视频可以私聊&#xff09; 摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 医疗服务系统&#xff0c;主要的模块包括查看管理员&#xff1b;首页、个人中心…

tomcat官网下载配置全部详细步骤(包含各种报错解决办法)

前言&#xff1a; 名字由来&#xff1a;翻译是野猫&#xff0c;tomcat的作者初衷是希望这个软件可以自力更生&#xff0c;自给自足。不依赖其他插件&#xff0c;独立达到提供web服务的效果 1.tocat和java的关系&#xff1f; tomcat是用Java语言编写的&#xff0c;需要运行在…

大三,请问现在自学Java还来得及吗?

前言 如果还在为入门Java晚而发愁时间够不够&#xff0c;首先你是准备自学&#xff0c;那么我们可以看看现在网络上一些比较热门的Java全体系的学习需要化多长时间&#xff0c;先拿B站上做的比较好的黑马教程和尚硅谷举例&#xff1a; 2022黑马程序员Java学习路线图​www.bili…