【算法与数据结构】并查集详解+题目

目录

一,什么是并查集

二,并查集的结构 

三,并查集的代码实现 

1,并查集的大致结构和初始化

2,find操作 

3,Union操作

4,优化 

小结:

四,并查集的应用场景

省份数量[OJ题] 


一,什么是并查集

核心概念:并查集是一种 用于管理元素分组 的数据结构。

在一些应用问题中,需将n个不同的元素划分成一些不相交的集合,开始时,n个元素各自成一个集合,然后按照一定规律将部分集合合成一个集合,也就是集合合并并查集(union-find)适合来描述这类问题。

对于并查集,我们可以将它看成是一个森林,森林是由多棵树组成的,并查集中的一个个集合就可以看作是树。

示例:

二,并查集的结构 

并查集的存储结构和树的双亲表示法相似。

所谓双亲表示法,就是在树的节点中,只存储父节点的指针,不存储孩子节点的指针。通过指针可以找到父节点。因为对于一颗树来说,可能有多个孩子 ,但只有一个父节点。

 

对于上图中:

节点0的数组值为-4,说明该节点为根节点。

节点6的数组值为0,说明该节点的父节点为0。

节点7的数组值为0,说明该节点的父节点为0。

节点8的数组值为0,说明该节点的父节点为0。

三,并查集的代码实现 

并查集主要支持一下操作:

  • 查询(find),查询一个元素在哪个集合中。
  • 合并(union),将两个集合合并为一个。

1,并查集的大致结构和初始化

class UnionFind
{
public:
    UnionFind(size_t n)
        :_ufs(n,-1)
    {}

    //......
private:
    vector<int> _ufs;
};

2,find操作 

在并查集中找到包含x的根

int findRoot(int x)
{
    int root = x;

    while (_ufs[root] >= 0)
        root = _ufs[root];

    return root;
}
 

3,Union操作

合并两个集合

void Union(int x1, int x2)
{
    int root1 = findRoot(x1);
    int root2 = findRoot(x2);
    if (root1 == root2)
        return; //在同一个集合中

    //这里在合并的时候采用数据量小的向数据量大的合并
    //也就是小树向大树合并
    if (abs(_ufs[root1]) < abs(_ufs[root2]))//root1节点更少
    {
        _ufs[root2] += _ufs[root1];
        _ufs[root1] = root2;   //小树合并到大树
    }
    else
    {
        //root2节点更少
        _ufs[root1] += _ufs[root2];
        _ufs[root2] = root1;
    }
}

4,优化 

当树比较高时,我们在反复查某个节点的根节点时,每次都会花费大量时间。

优化方法路径压缩,只要查找某个节点一次,就将查找路径上的所有节点挂到根节点下面。

如图:查找D的根A,查找路径上包含节点B,将节点D和节点B直接挂在根节点A的下面。

//路径压缩
int findRoot(int x)
{int root = x;while (_ufs[root] >= 0)root = _ufs[root];//路径压缩while (_ufs[x] >= 0){int parent = _ufs[x];_ufs[x] = root;   //挂在根节点的下面x = parent;}return root;
}

小结:

上述实现的并查集,支持连续元素。如果是处理非连续元素,需要使用哈希表代替数组(需额处理元素与索引的映射)。

核心思路:

  • 哈希映射unordered_map将任意类型元素映射为连续整数ID,内部用数组管理父节点
  • 动态扩容:自动添加新元素,无需预先指定规模。

  • 模板化:支持泛型数据类型(如string等)。

四,并查集的应用场景

  1. 连通性检测:判断网络中两个节点是否连通。

  2. 最小生成树(Kruskal算法):动态合并边,避免环。

  3. 社交网络分组:快速合并好友关系,查询是否属于同一社交圈。

总结:

并查集通过高效的查找与合并操作,成为处理动态连通性问题的核心数据结构。其优化方法(路径压缩、按秩合并)确保了接近常数的单次操作时间复杂度,适用于大规模数据场景。

其中的按秩合并就是合并集合时小树向大树合并。

省份数量[OJ题] 

题目链接:LCR 116. 省份数量 - 力扣(LeetCode)

 isConnected[i][j]=1,表示城市i和j连通,连通的城市为一个省份。用并查集将连通的数据放入一个集合,再统计最后的集合个数即可。

class Solution {
public:int findCircleNum(vector<vector<int>>& isConnected) {int n=isConnected.size();vector<int> _ufs(n,-1);//查找根auto find=[&](int x)->int{int root=x;while(_ufs[root]>=0)root=_ufs[root];return root;};for(int i=0;i<n;i++)for(int j=0;j<n;j++){if(isConnected[i][j]==1){//合并i和j集合int rooti=find(i),rootj=find(j);if(rooti!=rootj){_ufs[rooti]+=_ufs[rootj];_ufs[rootj]=rooti;}}}//统计集合数int ret=0;for(auto x:_ufs){if(x<0)ret++;}return ret;}
};

冗余连接[OJ题]

题目链接:684. 冗余连接 - 力扣(LeetCode)

class Solution {
public:vector<int> findRedundantConnection(vector<vector<int>>& edges) {//遍历edges数组//将在同一条边中的两个顶点放入一个集合//如果这条边的两个顶点已经在同一个集合中,加入这条边后,会出现环 ,返回这条边vector<int> ufs(1010);int sz=edges.size();//初始化时各元素自成一个集合,自己就是根for(int i=0;i<sz;i++)ufs[i]=i;for(int j=0;j<sz;j++){//找到边的两个顶点所在的集合,也就是根节点int root1=find(edges[j][0],ufs);int root2=find(edges[j][1],ufs);//如果在一个集合,加入这条边后,会出现环if(root1==root2)return edges[j];else{//两个集合独立,合并两个集合ufs[root1]=root2;}}return {0,0};}int find(int num,vector<int>& ufs){int root=num;while(ufs[root]!=root)root=ufs[root];return root;}
};

等式方程的可满足性[OJ题]

本题链接:990. 等式方程的可满足性 - 力扣(LeetCode)

class Solution {
public:bool equationsPossible(vector<string>& equations) {//并查集vector<int> ufs(26,-1);auto findroot=[&](int x){int parent=x;while(ufs[parent]>=0)parent=ufs[parent];return parent;};//将相等的放入同一集合中for(auto& str:equations)if(str[1]=='='){int root1=findroot(str[0]-'a');int root2=findroot(str[3]-'a');if(root1!=root2){ufs[root1]+=ufs[root2];ufs[root2]=root1;}}//遇到!,如果在同一个集合,返回falsefor(auto& str:equations){if(str[1]=='!'){int root1=findroot(str[0]-'a');int root2=findroot(str[3]-'a');if(root1==root2)return false;}}return true;}
};

 

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

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

相关文章

C语言简单练习题

文章目录 练习题一、计算n的阶乘bool类型 二、计算1!2!3!...10!三、计算数组arr中的元素个数二分法查找 四、动态打印字符Sleep()ms延时函数system("cls")清屏函数 五、模拟用户登录strcmp()函数 六、猜数字小游戏产生一个随机数randsrandRAND_MAX时间戳time() 示例 …

ShenNiusModularity项目源码学习(8:数据库操作)

ShenNiusModularity项目使用SqlSugar操作数据库。在ShenNius.Repository项目中定义了ServiceCollectionExtensions.AddSqlsugarSetup函数注册SqlSugar服务&#xff0c;并在ShenNius.Admin.API项目的ShenniusAdminApiModule.OnConfigureServices函数中调用&#xff0c;SqlSugar所…

MATLAB图像处理:图像特征概念及提取方法HOG、SIFT

图像特征是计算机视觉中用于描述图像内容的关键信息&#xff0c;其提取质量直接影响后续的目标检测、分类和匹配等任务性能。本文将系统解析 全局与局部特征的核心概念&#xff0c;深入讲解 HOG&#xff08;方向梯度直方图&#xff09;与SIFT&#xff08;尺度不变特征变换&…

java枚举类型的查找

AllArgsConstructor Getter public enum FileFilterRangeEnum {FILE_NAME("文件名称","fileName"),FILE_CONTENT("文件内容","fileContent");private final String text;private final String value;// 根据传入的字符串值查找对应的枚…

小白win10安装并配置yt-dlp

需要yt-dlp和ffmpeg 注意存放路径最好都是全英文 win10安装并配置yt-dlp 一、下载1.下载yt-dlp2. fffmpeg下载 二、配置环境三、cmd操作四、yt-dlp下视频操作 一、下载 1.下载yt-dlp yt-dlp地址 找到win的压缩包点下载&#xff0c;并解压 2. fffmpeg下载 ffmpeg官方下载 …

【技术解析】MultiPatchFormer:多尺度时间序列预测的全新突破

今天给我大家带来一篇最新的时间序列预测论文——MultiPatchFormer。这篇论文提出了一种基于Transformer的创新模型&#xff0c;旨在解决时间序列预测中的关键挑战&#xff0c;特别是在处理多尺度时间依赖性和复杂通道间相关性时的难题。MultiPatchFormer通过引入一维卷积技术&…

145,【5】 buuctf web [GWCTF 2019]mypassword

进入靶场 修改了url后才到了注册页面 注测后再登录 查看源码 都点进去看看 有个反馈页面 再查看源码 又有收获 // 检查$feedback是否为数组 if (is_array($feedback)) {// 如果是数组&#xff0c;弹出提示框提示反馈不合法echo "<script>alert(反馈不合法);<…

CTF-WEB: 利用iframe标签利用xss,waf过滤后再转换漏洞-- N1ctf Junior display

核心逻辑 // 获取 URL 查询参数的值 function getQueryParam(param) { // 使用 URLSearchParams 从 URL 查询字符串中提取参数 const urlParams new URLSearchParams(window.location.search); // 返回查询参数的值 return urlParams.get(param); } // 使用 DOMPuri…

晶闸管主要参数分析与损耗计算

1. 主要参数 断态正向可重复峰值电压 :是晶闸管在不损坏的情况下能够承受的正向最大阻断电压。断态正向不可重复峰值电压 :是晶闸管只有一次可以超过的正向最大阻断电压,一旦晶闸管超过此值就会损坏,一般情况下 反向可重复峰值电压 :是指晶闸管在不损坏的情况下能够承受的…

el-select 设置宽度 没效果

想实现下面的效果&#xff0c;一行两个&#xff0c;充满el-col12 然后设置了 width100%,当时一直没有效果 解决原因&#xff1a; el-form 添加了 inline 所以删除inline属性 即可

Python创建FastApi项目模板

1. 项目结构规范 myproject/ ├── app/ │ ├── core/ # 核心配置 │ │ ├── config.py # 环境配置 │ │ └── security.py # 安全配置 │ ├── routers/ # 路由模块 │ │ └── users.py # 用户路由 │ ├…

面试完整回答:SQL 分页查询中 limit 500000,10和 limit 10 速度一样快吗?

首先&#xff1a;在 SQL 分页查询中&#xff0c;LIMIT 500000, 10 和 LIMIT 10 的速度不会一样快&#xff0c;以下是原因和优化建议&#xff1a; 性能差异的原因 LIMIT 10&#xff1a; 只需要扫描前 10 条记录&#xff0c;然后返回结果。 性能非常高&#xff0c;因为数据库只…

一款利器提升 StarRocks 表结构设计效率

CloudDM 个人版是一款数据库数据管理客户端工具&#xff0c;支持 StarRocks 可视化建表&#xff0c;创建表时可选择分桶、配置数据模型。目前版本持续更新&#xff0c;在修改 StarRocks 表结构方面进一步优化&#xff0c;大幅提升 StarRocks 表结构设计效率。当前 CloudDM 个人…

数量5 - 平面图形、立体几何

目录 一、平面几何问题1.三角形2.其他图形二、立体几何与特殊几何1.表面积2.体积3.等比放缩(简单)4.几何最值(简单)5.最短路径一、平面几何问题 平面图形: 立体图形: 1.三角形 特殊直角

CAS单点登录(第7版)7.授权

如有疑问&#xff0c;请看视频&#xff1a;CAS单点登录&#xff08;第7版&#xff09; 授权 概述 授权和访问管理 可以使用以下策略实施授权策略以保护 CAS 中的应用程序和依赖方。 服务访问策略 服务访问策略允许您定义授权和访问策略&#xff0c;以控制对向 CAS 注册的…

53倍性能提升!TiDB 全局索引如何优化分区表查询?

作者&#xff1a; Defined2014 原文来源&#xff1a; https://tidb.net/blog/7077577f 什么是 TiDB 全局索引 在 TiDB 中&#xff0c;全局索引是一种定义在分区表上的索引类型&#xff0c;它允许索引分区与表分区之间建立一对多的映射关系&#xff0c;即一个索引分区可以对…

排序(Sortable)

排序&#xff08;Sortable&#xff09; 引言 在计算机科学和数据管理领域&#xff0c;排序算法是一项基本且重要的技能。排序算法能够将一组无序的数据转换为有序的数据&#xff0c;从而便于后续的数据处理和分析。本文将深入探讨排序算法的基本概念、常用排序方法、以及它们…

紫光展锐蜂窝物联网芯片V8850荣获国密一级安全认证

近日&#xff0c;紫光展锐蜂窝物联网芯片V8850荣获国密一级认证&#xff0c;标志着展锐V8850在安全能力方面获得权威认可&#xff0c;位居行业领先水平。这是紫光展锐继短距物联网芯片V5663在2020获得ARM PSA Level 2认证&#xff0c;蜂窝物联网芯片V8811在2021年获得ARM PSA L…

I.MX6ull-I2C

一,I2C总线介绍 I2C(Inter-Integrated Circuit 集成电路)总线是Philips公司在八十年代初推出的一种串行、半双工的总 线&#xff0c;主要用于近距离、低速的芯片之间的通信&#xff1b;I2C总线有两根双向的信号线&#xff0c;一根数据线SDA用于收 发数据&#xff0c;一根时钟线…

书籍推荐:《书法课》林曦

记得樊登老师说过&#xff0c;如果你想了解一个事物&#xff0c;就去读5本相关的书&#xff0c;你会比大部分人都更了解它。这是我读的第4本和“书法”有关的书&#xff0c;作为一个零基础的成年人&#xff0c;林曦这本《书法课》非常值得一读。&#xff08;无论你是否写字&…