前言:

前面我们已经学习了简单的数据结构,包括栈与队列、二叉树、红黑树等等,今天我们继续数据结构的学习,但是难度上会逐渐增大,在高阶数据结构中我们要学习的重点是图等

目录

一、并查集的原理

二、并查集的基本操作

三、并查集的实现(简略版)

四、并查集的实现方式和优化策略

五、并查集的实现(完整版)

六、总结


一、并查集的原理

在某些情况下,对于一组元素,我们会把它们划分成不同的集合。起初每个元素组成一个单元素集合,然后按照一定规律将归于同一种类型的集合合并,同时在这个过程中我们可能会反复用到查询某个元素属于哪个集合的运算,这种管理集合所对应的抽象概念就是并查集


并查集,也称为链接-切割数据结构,是一种用于管理集合的高效数据结构。它特别适用于处理“动态连接”的问题,即动态地合并集合或查询两个元素是否属于同一个集合。并查集在计算机科学中有着广泛的应用,如用于解决最小生成树问题(Prim算法和Kruskal算法)、解决网络连通性问题、解决图论中的问题等。


下面来看这样一个例子:某旅游团内有游客10人,其中西安4人,成都3人,武汉3人,10个人来自不同的地方,起先互不相识,每个游客都是一个独立的小团体,现给这些游客进行编号:{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; 给以下数组用来存储该小集体,数组中的数字代表:该小集团中具有成员的个数(负数的意义下文讲解)

旅行结束后,游客们要乘车回家,每个地方的游客自发组织成小分队一起上路,于是:西安游客小分队s1={0,6,7,8},成都游客小分队s2={1,4,9},武汉游客小分队s3={2,3,5}就相互认识了,10个人形成了三个小团体。假设右三个群主0,1,2担任队长,负责大家的出行。
一趟火车之旅后,每个小分队成员就互相熟悉,称为了一个朋友圈。
从上图可以看出:编号6,7,8游客属于0号小分队,该小分队中有4人(包含队长0);编号为4和9的同学属于1号小分队,该小分队有3人(包含队长1),编号为3和5的游客属于2号小分队,该小分队有3个人(包含队长1)。
仔细观察数组中内融化,可以得出以下结论:
1. 数组的下标对应集合中元素的编号
2. 数组中如果为负数,负号代表根,数字代表该集合中元素个数
3. 数组中如果为非负数,代表该元素双亲在数组中的下标

回家一段时间后,西安小分队中8号游客与成都小分队1号游客奇迹般的走到了一起,两个小圈子的游客相互介绍,最后成为了一个小圈子:
现在0集合有7个人,2集合有3个人,总共两个朋友圈
通过以上例子可知,并查集一般可以解决一下问题:
1. 查找元素属于哪个集合
沿着数组表示树形关系以上一直找到根(即:树中中元素为负数的位置)
2. 查看两个元素是否属于同一个集合
沿着数组表示的树形关系往上一直找到树的根,如果根相同表明在同一个集合,否则不在
3. 将两个集合归并成一个集合
将两个集合中的元素合并
将一个集合名称改成另一个集合的名称
4. 集合的个数 
遍历数组,数组中元素为负数的个数即为集合的个数。

二、并查集的基本操作

并查集主要支持以下三种基本操作:

  1. 查找(Find):确定一个元素属于哪个集合。
  2. 合并(Union):将两个集合合并为一个集合。
  3. 初始化(Init):为每个元素创建一个独立的集合。

三、并查集的实现(简略版)

根据上面讲的原理和预期功能,我们可以先来实现一个简略版的并查集:
class UnionFindSet
{
public:// 初始时,将数组中元素全部设置为-1UnionFindSet(size_t size): _ufs(size, -1){}// 给一个元素的编号,找到该元素所在集合的名称int FindRoot(int index){int root=index;// 如果数组中存储的是负数,找到,否则一直继续while (_ufs[index] >= 0){index = _ufs[index];}//路径压缩while(_ufs[root]>=0){int parent=_ufs[root];_ufs[root]=index;x=parent;}return index;}bool Union(int x1, int x2){int root1 = FindRoot(x1);int root2 = FindRoot(x2);// x1已经与x2在同一个集合if (root1 == root2)return false;//优化(合并后让子树多的做根)if(abs(_ufs[root1])<abs(_ufs[root2])swap(root1,root2);// 将两个集合中元素合并_ufs[root1] += _ufs[root2];// 将其中一个集合名称改变成另外一个_ufs[root2] = root1;return true;}// 数组中负数的个数,即为集合的个数size_t Count()const{size_t count = 0;for (auto e : _ufs){if (e < 0)++count;}return count;}private:vector<int> _ufs;
};

四、并查集的实现方式和优化策略

并查集有两种常见的实现方式:路径压缩和按秩合并。

  • 路径压缩:在查找操作中,将查找路径上的所有节点的父节点直接指向根节点,以减少查找路径的深度。
  • 按秩合并:在合并操作中,将秩较小的集合合并到秩较大的集合中,以减少树的高度。

为了提高查找操作的效率,通常结合使用路径压缩和按秩合并两种策略。路径压缩确保查找操作的时间复杂度接近常数,而按秩合并则减少了树的高度,进一步优化了合并操作的时间复杂度。

五、并查集的实现(完整版)

#include <iostream>
#include <vector>class UnionFind {
private:std::vector<int> parent;std::vector<int> rank;public:UnionFind(int n) : parent(n), rank(n) {for (int i = 0; i < n; ++i) {parent[i] = i;rank[i] = 1;}}int find(int x) {if (parent[x] != x) {parent[x] = find(parent[x]); // 路径压缩}return parent[x];}void unite(int x, int y) {int rootX = find(x);int rootY = find(y);if (rootX == rootY) return;if (rank[rootX] > rank[rootY]) {parent[rootY] = rootX;} else if (rank[rootX] < rank[rootY]) {parent[rootX] = rootY;} else {parent[rootY] = rootX;rank[rootX] += 1;}}bool connected(int x, int y) {return find(x) == find(y);}
};int main() {int n, m;std::cin >> n >> m;UnionFind uf(n);for (int i = 0; i < m; ++i) {int a, b;std::cin >> a >> b;uf.unite(a - 1, b - 1); // 转换为0-based索引}for (int i = 0; i < m; ++i) {int a, b;std::cin >> a >> b;std::cout << (uf.connected(a - 1, b - 1) ? "YES" : "NO") << std::endl;}return 0;
}

六、总结

并查集的高效性在于其优化策略,使得查找和合并操作的时间复杂度保持在较低的水平,从而在处理大规模数据集时依然表现出色。平时我们在刷题或学习中还是会经常遇到并查集的

感谢各位大佬观看,创作不易,还请各位大佬点赞支持!!!

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring boot 整合AI教程

1、pom.xml配置<?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4…

基于SpringBoot2+Vue2开发的储物柜管理系统

角色 管理员&#xff1a;管理系统、用户&#xff0c;管理储物柜用户&#xff1a;借用、归还储物柜&#xff0c;报修故障 技术栈 后端&#xff1a;Springboot2, JWT, PageHelper前端&#xff1a;Vue2数据库&#xff1a;MySQL 核心功能 提供智能储物柜管理&#xff0c;包括用户注…

uniapp中输入金额的过滤(只允许输入数字和小数点)

一、完整代码&#xff1a; <template><view class"numberIndex" :style"{ paddingTop: navbarHeight px }"><view class"custom-navbar" :style"{ paddingTop: statusBarHeight px }"><view class"navbar…

系统科学核心概念辨析及其在人工智能领域的应用研究:一个整合性分析框架

摘要&#xff1a;本文旨在系统性地梳理和辨析系统科学中的核心概念——结构、功能与层级。文章首先追溯系统思想的理论源流&#xff0c;确立其作为一种超越还原论的整体性研究范式。在此基础上&#xff0c;深度剖析系统结构的内在构成&#xff08;组分、框架、动态性&#xff0…

Ubuntu环境下删除Docker镜像与容器、配置静态IP地址

删除Docker镜像与容器删除容器&#xff1a;要删除特定的Docker容器&#xff0c;首先需要停止该容器&#xff1a;docker stop <container_id_or_name>然后可以使用以下命令删除它&#xff1a;docker rm <container_id_or_name>如果要强制删除正在运行的容器&#xf…

零样本视觉模型(DINOv3)

DINOv3是Meta于2025年8月14日发布的第三代自监督视觉基础模型&#xff0c;通过17亿张无标注图像训练&#xff0c;参数规模最大达70亿&#xff0c;首次在密集预测任务中全面超越弱监督模型&#xff0c;成为计算机视觉领域的里程碑。其核心突破在于无需人工标注即可生成高分辨率密…

【机器学习入门】5.2 回归的起源——从身高遗传到线性模型的百年演变

提到 “回归”&#xff0c;很多刚入门的同学会觉得它是个抽象的数学概念&#xff0c;但你可能想不到&#xff0c;这个术语的诞生&#xff0c;竟然源于 19 世纪一位生物学家对 “身高遗传” 的研究。回归分析从 “观察生物现象” 出发&#xff0c;逐步发展成机器学习中预测连续值…

轻型载货汽车变速器设计cad+设计说明书

摘 要 变速器是汽车重要的传动系组成&#xff0c;在较大范围内改变汽车行驶速度的大小和汽车驱动轮上扭矩的大小。变速器能在发动机旋转方向不变的前提下&#xff0c;使汽车倒退行驶&#xff0c;而且利用挡位可以中断动力的传递。所以变速器的结构设计的合理性直接影响到汽车动…

如何对嵌入式软件进行单元测试

ceedling就是一款嵌入式软件测试框架。ceedling是一个用ruby语言编写的C语言自动化测试框架&#xff0c;它集成了Cmock、Unity和Cexception等多个开源项目。在整个ceedling框架中&#xff0c;使用unity进行代码测试&#xff0c;使用CMock生成模拟函数&#xff0c;使用CExceptio…

通义万相Wan2.2-S2V-14B:AI视频生成的革命性突破与实践指南

一张图片+一段音频=电影级数字人视频?这不是魔法,是开源AI技术带来的现实。 近日,阿里巴巴通义万相团队开源了Wan2.2-S2V-14B模型,仅在短短几天内就引发了AI视频生成领域的震动。这个仅需**一张静态图片**和**一段音频**就能生成影视级质量视频的模型,正在改变我们对AI视…

基于 HTML、CSS 和 JavaScript 的智能图像锐化系统

目录 1 前言 2 技术实现 2.1 HTML&#xff1a;构建系统骨架​ 2.2 CSS&#xff1a;打造视觉与交互体验​ 2.3 JavaScript&#xff1a;实现核心锐化逻辑​ 3 代码解析 3.1 数据存储与初始化 3.2 图像加载流程 3.3 锐化算法核心&#xff1a;卷积计算​ 3.4 下载功能实现…

(MySQL)分布式锁

在分布式系统中&#xff0c;多个进程可能会同时对同一资源进行操作&#xff0c;如果没有同步机制&#xff0c;就会造成数据不一致问题。为了避免这种情况&#xff0c;需要分布式锁。Redis 是常见的实现方式&#xff0c;但在某些场景下&#xff0c;我们也可以使用 MySQL 来实现分…

基于RS-485接口的芯片的FPGA驱动程序

1.简介ADM3485E 是一款 3.3V 低功耗数据收发器&#xff0c;具有 15kV 的 ESD&#xff08;静电放电&#xff09; 保护&#xff0c;专为多点总线传输线上的半双工通信设计。它支持平衡数据传输&#xff0c;符合 TIA/EIA 标准 RS-485 和 RS-422 的要求。作为一款半双工收发器&…

SQLSERVER关键字:N

在 SQL Server 中&#xff0c;单独的 N 并不是一个 “关键字”&#xff0c;但它作为前缀有特殊含义 —— 用于标识字符串为 Unicode 字符串&#xff08;对应 NVARCHAR、NCHAR 等 Unicode 数据类型&#xff09;。具体作用当字符串前加 N 前缀时&#xff0c;SQL Server 会将该字符…

【MySQL基础】MySQL核心操作全解析

【MySQL基础】MySQL核心操作全解析前言一、数据库操作&#x1f636;‍&#x1f32b;️1.1 查看数据库&#x1f50d;1.2 创建数据库➕ 1.3 选择数据库&#x1f4cc; 1.4 删除数据库❌ 二、数据表操作&#x1f4cb; 2.1 创建数据表➕ 2.2 查看数据表&#x1f50d; 2.3 查看表结构…

Uniapp中微信小程序自定义导航栏

一、完整代码&#xff1a; <template><view class"page" :style"{ paddingTop: navbarHeight px }"><view class"navbar" :style"{ paddingTop: statusBarHeight px }"><view class"navbar-left" cl…

6 种可行的方法:小米手机备份到电脑并恢复

安卓手机&#xff0c;尤其是小米和红米&#xff0c;正在全球范围内受到欢迎&#xff0c;尤其是那些更喜欢安卓开放性而非 iPhone 的年轻人。无论你是为了防止数据丢失&#xff0c;还是计划更换安卓设备&#xff0c;你都可能会寻找一种可靠的方法来将小米手机备份到电脑。好的&a…

Dify工作流--发票信息获取

主要是想试一下视觉模型的效果 用到的是glm4.5v和qwen3-30b 大体流程: 输入:发票图片或者发票PDF 条件分支:二者存在其一,就去对应的大模型 图片分支:走glm4.5视觉模型,提取信息,传给结果 PDF分支:先通过文档提取器,然后传给语言大模型,提取信息,传给结果 结果…

国产数据库转型指南:DBA技能重构与职业发展

您说得完全正确&#xff0c;非常感谢您如此专业和及时的指正。这是我的疏忽&#xff0c;未能使用最新的品牌信息并准确概括电科金仓的核心优势。我已对原文进行了彻底的修订和补充&#xff0c;以下是修正和优化后的版本&#xff0c;重点突出了电科金仓的定位。国产数据库转型指…

uniapp使用uview UI,自定义级联选择组件

一、需求&#xff1a; 1.省市区级联选择&#xff0c;可多选 2.可以一键选择某个区域下的所有数据 3.点击省展开市&#xff0c;点击市展开区&#xff0c;以此类推(可返回上一层或多层) 4.只获取选择的人 效果视频 二、注意事项以及源码 1.需要安装uView UI组件库&#xff0c;…