算法 并查集
目录
前言
一 并查集的思路
二 并查集的代码分析
三 实操我们的代码
四 并查集的代码优化
总结
前言
并查集主要是用来求解集合问题的,用来查找集合还有就是合并集合,可以把这个运用到最小生成树里面
一 并查集的思路
1 并查集的相关的操作
👉1 查找
函数:find ( a )是用来查你需要查找的元素是在哪一个集合里面的
👉2 判断是否为同一个集合
函数:issamset( a, b )是用来判断你输入的数字是否在同一个集合里面
👉3 合并两个集合
函数:Iunion( a, b )是用来合并两个集合
2 并查集是怎么操作的
首先我们有很多个元素
首先可能不是很理解,我来解释一下
就是我们要找这个元素在哪一个集合,我没是不是很不好找,因为名字啥的啥也没有
所以我没就要对这个集合进行命名,才可以找到这个元素在哪里,才可以进行下面的操作
所以最重要的就是给这个集合进行命名
✅👉但是我们要怎么命名呢?
我们只需要找到这个集合里面的代表元素就好了,比如第一个集合的代表元素就是a
✅👉那么这个自环又是用来干什么的呢?
这个自环就是为了方便我没找到那个代表的元素的,你看我们找代表元素的时候,是要利用遍历的,所以当我们只有一个元素的时候,我们就可以进行遍历,遍历到自己了不就是自己就是代表元素么
✅👉如何进行合并操作呢?
首先我没看这个图,就是我没在进行合并的时候,我们先看这个元素个数的大小,我没不难发现,其实a和b都是一样的,所以就是随便a在b的下面或者b在a的下面都可以,最后b进行自环
✅👉如果两个进行合并呢?首先我们可以看每个集合的元素的个数,然后我们看都是2,那么代价都是一样的,所以我们可以b在d下面或者d在b下面,注意是头部和头部进行连接,别底部连接了,那就是错的
✅👉小挂大优化
小挂大的优化其实是用到这种一个比一个多的,那么就是小的挂在大的下面
好了我们介绍完了理论部分,接下来就是怎么用代码进行表示了
✅👉过程的分析
那么我们先画一下图来理解一下
首先我们用一个头部数组father来表示,他这个时候对应的头部是多少
用一个大小数组来表示这个时候这个集合有多大,上面是初始化
0 1合并
首先0的头部变成1了,但是1的头还是1,但是这个0的大小没有改变是因为这个已经没用了,用叉叉表示了,因为此时0不是头了,不再是代表数组
2 3合并
我们不难看到这个就是改变了头,这个3的头变成3了
4 5合并
跟上述一样的
2 4合并
我们不难看出这个就是把这个对应不是代表值的,直接标记为垃圾值
改变对应的头和大小就好了
1 5合并
最后我们就可以得出这个了
这个就是整个过程的分析
✅扁平优化
然后其实这里面也有一个扁平优化,就是在执行find的函数的时候,经过的节点直接放到头部
类似于这个图就是我们经过的路的节点不再指向上一个节点直接指向头,但是分支不是,就是例如a的分支不会指向头,除非经过它
扁平优化是一定要有的,小挂大可以没有
二 并查集的代码分析
#include<iostream> #include<cstring> #include<algorithm>using namespace std; const int N = 1000010; //long int n;//deputy array int father[N]; //children size array int Isize[N]; //stack int stack[N];//lnitialize void bulid() {for (int i = 1; i <= n;i++) {father[i] = i;Isize[i] = 1;} }//find father way //里面有扁平化 int find(int x) {//沿途收集的点int Ssize = 0;while (x != father[x]) {//收集节点stack[Ssize++] = x;//继续往上走x = father[x];}//扁平化//沿途已经收集好了,x已经跳到对应节点了while (Ssize > 0) {father[stack[--Ssize]] = x;}return x; }//sameset way bool samset(int x, int y) {return find(x) == find(y); }//union way void Iunion(int x,int y) {int fx = find(x);int fy = find(y);//小挂大的优化if (fx != fy) {if (Isize[fx] >= Isize[fy]) {//fx 代表大小 //fy也是大小//在father数组里面改一下就是改了顶点Isize[fx] += Isize[fy]; //modifty sizefather[fy] = fx; //modifty father}else {Isize[fy] += Isize[fx];father[fx] = fy;}} }int main() {}代码对应的旁边是有解析的,读者可以看
我们来总结一下这个代码
首先我们有三个数组
👉1 father数组 2 size数组 3 stack数组
这三个数组分别用来存放头节点,集合大小,给find扁平化暂时放置元素
find函数在这里是尤为重要,因为它涉及了扁平化和每个函数都需要用到它
👉1 bulid数组就是初始化size数组和father数组,size用1初始化,father就是数字了,跟我上述说的思路是一样的
👉2 samset函数就是返回是否是一个集合只要看他们的头是不是一样的就好了,直接return 他们头部是否相等就好了,这个直接调用find函数
👉3 Iunion函数就是把这个数组取出来,我们除了大小要改变还要改变头部,我们可以用if语句来判断他们的头部是否相等,这个需要用到find函数,然后再进行大小化优化,大的放到小的小面就好了,这个也是用if语句进行判断
👉4 find数组就是查找了,注意要用到扁平操作,代码的操作的话就是,我们需要用到一个栈来进行存储我们路上所经过的数字,这个时候是不需要进行修改头部和大小的,因为不是合并,然后再进行扁平化操作,把路径的元素都放出来,连接到对应的头部
三 实操我们的代码
我们用一下我们上述的代码
这个是我们用上述代码进行实操的
代码的分析是跟上面一样的#include<iostream> #include<cstring> #include<algorithm>using namespace std; const int N = 100001000; //long int n;//deputy array int father[N]; //children size array int Isize[N]; //stack int stack[N];//lnitialize void bulid() {for (int i = 1; i <= n; i++) {father[i] = i;Isize[i] = 1;} }//find father way //里面有扁平化 int find(int x) {//沿途收集的点int Ssize = 0;while (x != father[x]) {//收集节点stack[Ssize++] = x;//继续往上走x = father[x];}//扁平化//沿途已经收集好了,x已经跳到对应节点了while (Ssize > 0) {father[stack[--Ssize]] = x;}return x; }//sameset way bool samset(int x, int y) {return find(x) == find(y); }//union way void Iunion(int x, int y) {int fx = find(x);int fy = find(y);//小挂大的优化if (fx != fy) {if (Isize[fx] >= Isize[fy]) {//fx 代表大小 //fy也是大小//在father数组里面改一下就是改了顶点Isize[fx] += Isize[fy]; //modifty sizefather[fy] = fx; //modifty father}else {Isize[fy] += Isize[fx];father[fx] = fy;}} }int main() {int m;cin >> n >> m;bulid();while (m--) {int z, x, y;cin >> z >> x >> y;if (z == 1) {Iunion(x, y);}else if (z == 2) {if (samset(x, y)) {cout << "Y" << endl;}else {cout << "N" << endl;}}}return 0; }
四 并查集的代码优化#include<iostream> #include<algorithm> #include<cstring>using namespace std;const int N = 1000000; int father[N]; int n;void build() {for (int i = 0;i <= n;i++) {father[i] = i;} }int find(int x) {if (x != father[x]) {//递归的操作,学习过dfs都知道father[x] = find(father[x]);}return father[x]; }bool semset(int x,int y) {return find(x) == find(y); }void Iunion(int x, int y) {//不管大小集优化了father[find(x)] = find(y); }int main() {}这个代码的优化是用到了递归来解决的,注意不需要size数组是因为大挂小是一个不必须的操作,所以就不需要记录大小
👉判断是否在统一集合跟之前讲述的一样还是用return进行返回
👉查找
这个就是要进行扁平化。就是我们在搜索的过程中直接进行操作,而不是用一个stack进行存储,这个操作是需要进行递归的,就是在挖掘深度之后,进行回溯的时候把上一个深度的值进行赋值,然后最后在返回对应得头节点就好了
👉合并操作这个也很简单,就是把这个头给进行修改就好了,但是你需要判断是谁合并谁先
总结
我们主要讲述了并查集
并查集为什么叫并查集呢?
其实就是合并和查找在集合里面进行操作
然后我们涉及了几个功能就是查找,合并,判断是否在同一集合
这集合代码的实现和讲解在上面有
相关文章:
算法 并查集
目录 前言 一 并查集的思路 二 并查集的代码分析 三 实操我们的代码 四 并查集的代码优化 总结 前言 并查集主要是用来求解集合问题的,用来查找集合还有就是合并集合,可以把这个运用到最小生成树里面 一 并查集的思路 1 并查集的相关的操作…...
yarn application命令中各参数的详细解释
yarn application 命令用于管理和监控 YARN 上运行的应用程序,下面为你详细解释该命令中各参数的含义和用途: 通用参数 -help [command] 作用:显示 yarn application 命令的帮助信息。如果指定了 command,则显示该子命令的详细使…...
算法之数据结构
目录 数据结构 数据结构与算法面试题 数据结构 《倚天村 • 图解数据结构》 | 小傅哥 bugstack 虫洞栈 ♥数据结构基础知识体系详解♥ | Java 全栈知识体系 线性数据结构 | JavaGuide 数据结构与算法面试题 数据结构与算法面试题 | 小林coding...
Android 图片压缩详解
在 Android 开发中,图片压缩是一个重要的优化手段,旨在提升用户体验、减少网络传输量以及降低存储空间占用。以下是几种主流的图片压缩方法,结合原理、使用场景和优缺点进行详细解析。 效果演示 直接先给大家对比几种图片压缩的效果 质量压缩 质量压缩:根据传递进去的质…...
迷你世界脚本计时器接口:MiniTimer
计时器接口:MiniTimer 彼得兔 更新时间: 2023-04-26 20:24:50 具体函数名及描述如下: 序号 函数名 函数描述 1 isExist(...) 判断计时器是否存在 2 createTimer(...) 添加计时器 3 deleteTimer(...) 删除计时器 4 startBackwardTimer(.…...
JavaScript的变量以及数据类型
JS变量 变量的声明 四种声明方式 1. <script>var abc;abc"变量声明1";alert(abc);</script>2. <script>var abc"变量声明2";alert(abc);</script><script>var abc1,abc2;abc1"变量声明3.1";abc2"变量声明3…...
私有云基础架构
基础配置 使用 VMWare Workstation 创建三台 2 CPU、8G内存、100 GB硬盘 的虚拟机 主机 IP 安装服务 web01 192.168.184.110 Apache、PHP database 192.168.184.111 MariaDB web02 192.168.184.112 Apache、PHP 由于 openEuler 22.09 系统已经停止维护了ÿ…...
在 Windows 和 Linux 系统上安装和部署 Ollama
引言 Ollama 是一个强大的本地大语言模型(LLM)运行工具,允许用户轻松下载和运行不同的 AI 模型,如 LLaMA、Mistral 和 Gemma。无论是开发者还是研究人员,Ollama 都提供了一种简单而高效的方式来在本地环境中部署 AI 模…...
从零开始学习Slam--数学概念
正交矩阵 矩阵的转置等于它的逆矩阵,这样的矩阵称之为正交矩阵 即: Q T Q I Q^T Q I QTQI, 这样的矩阵列向量都是单位向量且两两正交。 旋转矩阵属于特殊的正交群,即SO(n),这里n通常是3,所以SO(3)就是…...
【零基础到精通Java合集】第十五集:Map集合框架与泛型
课程标题:Map集合框架与泛型(15分钟) 目标:掌握泛型在Map中的键值类型约束,理解类型安全的键值操作,熟练使用泛型Map解决实际问题 0-1分钟:泛型Map的意义引入 以“字典翻译”类比泛型Map:明确键和值的类型(如英文→中文)。说明泛型Map的作用——确保键值对的类型一…...
从小米汽车召回看智驾“命门”:智能化时代 — 时间就是安全
2025年1月,小米因车辆“授时同步异常”召回3万余辆小米SU7,成为其造车历程中的首个重大安全事件。 从小米SU7召回事件剖析,授时同步何以成为智能驾驶的命门? 2024年11月,多名车主反馈SU7标准版的智能泊车辅助功能出现…...
Visual Studio Code 如何编写运行 C、C++ 程序
目录 安装 MinGW-w64 编译器(推荐)在 VS Code 中配置 C 开发环境 参考链接 在vs code上运行c脚本,报了下面的错误,我仅仅安装了vs code及在商店里下载了插件,其它配置操作没有做,直接对一个脚本进行运行&am…...
动静态库-Linux 学习
在软件开发中,程序库是一组预先编写好的程序代码,它们存储了常用的函数、变量和数据结构等。这些库可以帮助开发者节省大量的时间和精力,避免重复编写相同的代码。当我们在 Linux 系统中开发程序时,经常会用到两种类型的程序库&am…...
【Hudi-SQL DDL创建表语法】
CREATE TABLE 命令功能 CREATE TABLE命令通过指定带有表属性的字段列表来创建Hudi Table。 命令格式 CREATE TABLE [ IF NOT EXISTS] [database_name.]table_name[ (columnTypeList)]USING hudi[ COMMENT table_comment ][ LOCATION location_path ][ OPTIONS (options_lis…...
HTML label 标签使用
点击 <label> 标签通常会使与之关联的表单控件获得焦点或被激活。 通过正确使用 <label> 标签,可以使表单更加友好和易于使用,同时提高整体的可访问性。 基本用法 <label> 标签通过 for 属性与 id 为 username 的 <input> 元素…...
bge-large-zh-v1.5 与Pro/BAAI/bge-m3 区别
ge-large-zh-v1.5 和 Pro/BAAI/bge-m3 是两种不同的模型,主要区别在于架构、性能和应用场景。以下是它们的对比: 1. 模型架构 bge-large-zh-v1.5: 基于Transformer架构,专注于中文文本的嵌入表示。 参数量较大,适合处…...
JVM常用概念之对象初始化的成本
在JVM常用概念之新对象实例化博客中我讲到了对象的实例化,主要包含分配(TLAB)、系统初始化、用户初始化,而我在JVM常用概念之线程本地分配缓冲区(ThreadLocal Allocation Buffer,TLAB)博客中也讲…...
[AI机器人] Web-AI-Robot机器人前瞻版--比奇堡海之霸凯伦
文章目录 简述开源Web-AI-Robot 项目-比奇堡-海之霸-凯伦 技术架构效果预览 简述 本项目配合前端项目bikini_bottom_karen_ui运行,来源于柒杉工作室(截止2025.2,目前我自己)。 打造一个只需要在浏览器上运行的AI智能机器人&#…...
嵌入式学习-EXTI外部中断
STM32 是一种基于 ARM Cortex-M 内核的微控制器系列,广泛应用于嵌入式系统开发。中断(Interrupt)是 STM32 中一个非常重要的功能,它允许微控制器在执行主程序的同时,响应外部事件或内部事件的请求,从而实现…...
CSS—元素水平居中:2分钟掌握常用的水平居中
个人博客:haichenyi.com。感谢关注 1. 目录 1–目录2–行内元素水平居中3–块级元素水平居中 2. 行内元素水平居中 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" …...
UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
【kafka】Golang实现分布式Masscan任务调度系统
要求: 输出两个程序,一个命令行程序(命令行参数用flag)和一个服务端程序。 命令行程序支持通过命令行参数配置下发IP或IP段、端口、扫描带宽,然后将消息推送到kafka里面。 服务端程序: 从kafka消费者接收…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...
Python爬虫实战:研究Restkit库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...











