【CSP考点回顾】并查集(1)

并查集

并查集是一种简单而高效的数据结构,主要用于处理一些分离的元素集合的合并与查询问题。它在计算机科学中应用广泛,尤其适用于那些需要动态管理和查询元素分组情况的场景,如网络连接、图的连通分量、社交网络中的群组划分等。通过并查集,我们可以快速判断两个元素是否属于同一个集合,以及将两个不同的集合合并为一个。其高效的操作使得并查集成为处理大型数据集中群组、连通性等问题的首选数据结构。

1.并查集操作

  1. 查找(Find):确定特定元素属于哪个子集。此操作可帮助确定两个元素是否属于同一子集。

  2. 合并(Union 或 Merge):将两个子集合并成一个单独的子集。

2.实现方法

方法1:快速查找

快速查找的思想是利用一个数组来跟踪每个元素所属的集合。在这种方法中,数组的每个位置对应一个元素,数组中存储的值代表该元素所属的集合标识符。这里的“集合标识符”通常是该集合中某个元素的标识,通常是这个集合中最小的元素,但实际上可以是任何标识。(假设有一个名为Set的数组,其大小是N(元素的数量)。初始时,每个元素都属于只包含其自身的集合,因此Set[i] = i 对于所有0 <= i < N。)

i.查找操作 (Find)

查找操作非常简单且直接:给定元素x,函数find1只需返回数组中x位置上的值。这个值就是x所属的集合的标识符。因为直接通过索引访问数组,所以这个操作的时间复杂度是O(1)。

// 查找操作
int find1(int x) {return Set[x];
}
ii.合并操作 (Union or Merge)

合并操作涉及到将两个集合合并为一个。这需要将这两个集合中的所有元素更新为拥有相同的集合标识符。在快速查找策略中,这通常涉及到遍历整个数组,将所有属于这两个集合之一的元素的集合标识符更新为统一的值(通常是两个集合标识符中的最小值)。因为这涉及到遍历整个数组,所以时间复杂度为O(N)。

// 合并操作
void merge1(int a, int b) {int setA = find1(a); // 找到a的集合标识符int setB = find1(b); // 找到b的集合标识符if (setA != setB) {  // 如果a和b不在同一集合,则合并for (int i = 0; i < N; ++i) {if (Set[i] == setB) { // 将所有属于集合B的元素的集合标识符更新为A的集合标识符Set[i] = setA;}}}
}

方法2:快速合并

快速合并优化了合并集合的操作,但是这使得查找操作可能变慢。在快速合并的实现中,每个集合都由一个树来表示,集合中的每个元素都是树的一个节点。每个节点都指向另一个节点(除了根节点,它指向自己),这个指向表示了元素之间的关联。集合的“根”节点是该集合的代表。

i.查找操作 (Find)

查找操作find2需要找到元素所在集合的根节点,因为根节点是该集合的代表。开始时,find2函数从指定的节点开始,沿着指向父节点的指针向上遍历,直到找到一个指向自己的节点,即根节点。这个过程可能需要遍历整个树的高度,所以在最坏的情况下时间复杂度为O(N)。

int find(int x) {while (parent[x] != x) {  // 当x不是自己的父亲(即不是根元素)时parent[x] = parent[parent[x]]; // 进行路径压缩,将x的父亲设置为x的爷爷节点x = parent[x]; // x上移至其父亲节点}return x; // 返回x的根元素,即集合的标识
}
ii.合并操作 (Union or Merge)

合并操作merge2简单到只需要将一个集合的根节点指向另一个集合的根节点。因为这只需要更改一个节点的父指针,所以这个操作的时间复杂度是O(1)。

// 合并操作
void merge2(int a, int b) {int rootA = find2(a); // 找到a的根int rootB = find2(b); // 找到b的根if (rootA != rootB) {  // 如果a和b不在同一集合,将一个集合的根指向另一个集合的根Set[rootA] = rootB;}
}
iii.路径压缩优化

为了改善查找操作的效率,可以应用路径压缩技术。当执行查找操作以找到一个元素的根节点时,路径压缩将所有遍历过的节点直接连接到根节点上,这样它们在下一次查找时将直接指向根节点,大大减少了遍历的路径长度。通过这种方式,查找操作的平均时间复杂度可以显著减少。

// 查找操作,带路径压缩
int find2(int x) {if (Set[x] != x) {Set[x] = find2(Set[x]); // 路径压缩}return Set[x];
}
iv.基于秩的合并

基于秩的合并是一种优化并查集性能的策略,尤其是在mergefind操作上。在这种策略中,我们通过保持树的高度尽可能低来提高效率。这里的“秩”可以理解为树的高度或深度的一个估计值,并不一定是实际的高度

每个元素都有一个秩,初始时秩都设置为0。当两个集合合并时,如果它们的秩相同,则选择一个作为新的根,并将其秩增加1;如果它们的秩不同,则将秩较小的树合并到秩较大的树下,而不改变秩较大树的秩。这样做可以避免树变得太高,保证了find操作的效率。

class UnionFind {vector<int> parent; // 存储每个元素的父节点vector<int> rank;   // 存储每个根节点的秩public:UnionFind(int size) : parent(size), rank(size, 0) {// 初始时,每个元素的父节点是它们自己for (int i = 0; i < size; ++i) {parent[i] = i;}}// 查找元素x所在集合的根节点int find(int x) {if (parent[x] != x) {// 路径压缩parent[x] = find(parent[x]);}return parent[x];}// 合并元素x和元素y所在的集合void merge(int x, int y) {int rootX = find(x);int rootY = find(y);if (rootX != rootY) {// 将秩较小的树的根连接到秩较大的树的根if (rank[rootX] < rank[rootY]) {parent[rootX] = rootY;} else if (rank[rootX] > rank[rootY]) {parent[rootY] = rootX;} else {// 如果秩相等,则任选一个作为根,并增加其秩parent[rootY] = rootX;rank[rootX] += 1;}}}
};

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

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

相关文章

Windows系统搭建Cloudreve结合内网穿透打造可公网访问的私有云盘

目录 ⛳️推荐 1、前言 2、本地网站搭建 2.1 环境使用 2.2 支持组件选择 2.3 网页安装 2.4 测试和使用 2.5 问题解决 3、本地网页发布 3.1 cpolar云端设置 3.2 cpolar本地设置 4、公网访问测试 5、结语 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站&#xff…

通讯芯片D3232简介——主要用于工控主板、工业控制器、新能源充电桩等众多涉及RS232通讯的产品。

一、应用领域 D3232芯片主要用于工控主板、工业控制器、程序烧录下载器、仿真器、新能源充电桩等众多涉及RS232通讯的产品。 二、基本特性 D3232芯片由两个线路驱动器、两个线路接收器和双电荷泵电路组成&#xff0c;具有HBM>15kV、CDM>2kV的ESD保护能力&#xff0c;并且…

leetcode解题思路分析(一百五十三)1342 - 1344 题

将数字变成 0 的操作次数 给你一个非负整数 num &#xff0c;请你返回将它变成 0 所需要的步数。 如果当前数字是偶数&#xff0c;你需要把它除以 2 &#xff1b;否则&#xff0c;减去 1 。 直接做就完事 class Solution { public:int numberOfSteps(int num) {int nCnt 0;w…

Java Web项目—餐饮管理系统Day02-管理员后台开发(一)登录

文章目录 1. 创建实体类2. 创建三层调用结构mapperservicecontroller 3. 登录逻辑实现4. 过滤器/拦截器 登录功能开发, 主要是要校验登录账号及密码的准确性, 注意密码使用 base64 加密. 另外一个最重要的是要记住当前用户的id以记住登录状态, 并使用拦截器, 对于部分请求, 需要…

从原理总结chatGPT的Prompt的方法

ChatGPT的Prompt方法是一种引导模型生成对话的技术&#xff0c;它基于前面已经提供的上下文信息&#xff0c;以及一个特定的输入格式来指导模型生成合理、连贯的回答。以下是ChatGPT Prompt方法的原理总结&#xff1a; 输入格式&#xff1a;Prompt方法将对话分为多个轮次&#…

外观模式实战运用

前言 即使在没有学习过设计模式之前&#xff0c;只要是写过代码&#xff0c;都会在不经意间使用到外观模式&#xff0c;或者说用到了外观模式的思想。 外观模式的定义&#xff1a;通过创建一个统一的高层接口&#xff0c;使得复杂的子系统更加容易使用。这个模式为复杂的系统…

Seata 2.x 系列【10】回滚日志表 undo_log

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Seata 版本 2.0.0 本系列Spring Boot 版本 3.2.0 本系列Spring Cloud 版本 2023.0.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-seata-demo 文章目录 1. 概述2. 表语句…

【Java 并发】AbstractQueuedSynchronizer 中的 Condition

1 简介 任何一个 Java 对象都天然继承于 Object 类, 在线程间实现通信的往往会应用到 Object 的几个方法, 比如 wait(), wait(long timeout), wait(long timeout, int nanos) 与 notify(), notifyAll() 几个方法实现等待 / 通知机制。同样的, 在 Java Lock 体系下也有同样的方…

[C++核心编程](十):文件操作

目录 文件类型 文件三大类 写文本文件 读文本文件 写二进制文件 读二进制文件 文件打开方式 程序运行时产生的数据都属于临时数据&#xff0c;程序一旦运行结束都会被释放&#xff0c;因此通过文件可以将数据持久化 C中对文件操作需要包含头文件<fstream> 文件类…

每日shell脚本之邮件

每日shell脚本之邮件 以下是一个简单的脚本&#xff0c;它接收三个参数&#xff1a;收件人地址、邮件主题和邮件内容。这个脚本将使用系统的默认邮件服务器来发送邮件。 #!/bin/bash# 检查参数数量 if [ $# -ne 3 ]; thenecho "使用方法&#xff1a; $0 <收件人邮箱&…

工具篇--分布式定时任务springBoot--elasticjob简单使用(1)

文章目录 前言一、elasticjob 介绍&#xff1a;二、elasticjob 使用&#xff1a;2.1 部署zookeeper&#xff1a;2.2 引入库2.2 定义任务&#xff1a;2.3 任务执行&#xff1a;2.4 任务执行控制台输出&#xff1a; 三、elasticjob 启动错误&#xff1a;3.1 KeeperErrorCode Ope…

Linux系统架构----Nginx的服务优化

Linux系统架构----Nginx的服务优化 一.隐藏版本号 在生产环境中&#xff0c;需要隐藏Nginx的版本号&#xff0c;以免泄露Nginx的版本&#xff0c;使得攻击者不能针对特定版本进行攻击 查看Nginx的版本有两种方法 使用fiddler工具抓取数据包&#xff0c;查看Nginx版本 在Cen…

【Node.js从基础到高级运用】十二、身份验证与授权:JWT

身份验证与授权是现代Web应用中不可或缺的部分。了解如何在Node.js应用中实施这些机制&#xff0c;将使你能够构建更安全、更可靠的应用程序。本文将引导你通过使用JWT实现用户注册、登录和权限控制的过程。 JWT&#xff08;Json Web Token&#xff09; JWT是一种用于双方之间…

蓝桥杯深度优先搜索|剪枝|N皇后问题|路径之谜(C++)

搜索&#xff1a;暴力法算法思想的具体实现 搜索&#xff1a;通用的方法&#xff0c;一个问题如果比较难&#xff0c;那么先尝试一下搜索&#xff0c;或许能启发出更好的算法 技巧&#xff1a;竞赛时遇到不会的难题&#xff0c;用搜索提交一下&#xff0c;说不定部分判题数据很…

R语言tidycmprsk包分析竞争风险模型

竞争风险模型就是指在临床事件中出现和它竞争的结局事件&#xff0c;这是事件会导致原有结局的改变&#xff0c;因此叫做竞争风险模型。比如我们想观察患者肿瘤的复发情况&#xff0c;但是患者在观察期突然车祸死亡&#xff0c;或者因其他疾病死亡&#xff0c;这样我们就观察不…

基于单片机的太阳能热水器控制系统设计与仿真

目录 摘要 3 Controling system design and simulation of the solar water heater based on single chip microcomputer 4 第一章 前言 5 1.1设计背景和意义 5 1.2国内外的发展趋势 5 第二章 系统设计总览 7 2.1控制中心 7 2.2外围设备 7 第三章 系统硬件设计 8 3.1 总硬件的…

小程序路由跳转---事件通信通道EventChannel(二)

事件通信通道EventChannel实现两个页面之间的数据传输已在上篇小程序路由跳转—事件通信通道EventChannel&#xff08;一&#xff09;展开叙述&#xff0c;接下来讨论下多个页面&#xff08;三个及以上&#xff09;数据的通道如何构建。 本文重点&#xff1a;三个以上页面需将…

jenkin部署spring boot项目【从0到1】

写在前面&#xff0c;遇到的很多错误 本来想用docker启动Jenkins的&#xff0c;也这样做了&#xff0c;但是遇到了一个非常严重的问题&#xff0c;就是mvn命令在docker里面不生效&#xff0c;然后就修改文件&#xff0c;但是发现vi不存在&#xff0c;好的。接着用yum安装vi工具…

【Stable Diffusion】入门-02:AI绘画提示词+参数设置攻略

目录 1 提示词1.1 分类和书写方式1.1.1 内容型提示词1.1.2 标准化提示词1.1.3 通用模板 1.2 权重1.2.1 套括号1.2.2 数字权重1.2.3 进阶语法 1.3 负面提示词 2 参数详解2.1 Sampling steps2.2 Sampling method2.3 Width, Height2.4 CFG Scale2.5 Seed2.6 Batch count, Batch si…

Vue2 引入自己下载的SVG图像的方式

Vue2 引入下载的SVG图像的方式 Step 1&#xff1a;安装依赖 npm i svg-sprite-loader --saveStep 2&#xff1a;创建文件路径 // index.js import Vue from vue import SvgIcon from /components/SvgIcon// svg component// register globally Vue.component(svg-icon, Svg…