c++并查集(详细总结)

article/2025/8/27 0:00:11

老话重谈,先看定义

并查集是一种树型的数据结构,用于处理一些不相交集合(disjoint sets)的合并及查询问题。常常在使用中以森林来表示。

首先得明白一些概念:
什么是树,什么是森林(由树组成的叫森林hh),什么是集合
这些问题是其他范畴的知识,就不过多累赘了,不了解的同学建议提前了解先。

下面我们切入重点

1、并查集

首先,我个人认为并查集在逻辑上是一个森林,该森林内由一棵或多棵数组成,如下举个例子
在这里插入图片描述
这三棵树可以组成一个森林,而这个森林可以叫并查集,每棵树可以称为并查集分量,这是逻辑上的理解

显式上理解,大部分情况并查集是以数组的方式进行存储的

有一些如下性质

  • 每一个并查集分量(也就是每一棵树)都有一个根结点,比如上面三棵树的根结点分别是1,2,10
  • 所属同一个并查集分量的结点的根结点是相同的,比如6,7,8的根结点都是10,所以这三个结点位于同一个并查集分量内,也就是同一颗树上
  • 并查集每一个分量都是相互独立,互不影响的!
  • 并查集内所有节点的值一定是互不相同的

2、常用并查集方法

在讲方法之前我们需要定义一些并查集需要用到的数据

数据存储作用及举例
parent[]parent[ i ] = j 表示 节点 i 的父节点是 j(比如上面根结点为10的那棵树,有 parent[ 7 ] = 6 , parent[ 6 ] = 10 …
count是一个int类型的变量,表示该并查集内有多少个并查集分量,也就是说并查集这个森林里面有多少课树(比如上面的例子中有三个树,所以count=3

我们先定义并查集的数据结构代码(这里采用c++)

class DisjointSets{public:// 给个默认值,默认是10int count = 10;// vector的好处是可以动态修复数组大小vector<int> parent;// 类的有参构造方法DisjointSets(int count){this->count = count;// 对parent数组进行初始化for(int i=0;i<=count;++i)// 默认这个森林有count棵树,//而且每棵树只有一个节点,也就是// 根结点,默认根结点的父节点是根结点本身parent[i] = i;}// 类的析构函数,销毁类实例前调用~DisjointSets(){}// 并查集的方法定义-----------------// 查找一个节点所属树的根节点int findParentNode(int x);// 合并两棵树void unionSetNode(int x,int y);        
};

2.1、并查集——查找某个节点的根结点

int DisjointSets::findParentNode(int x){// 如果x的父节点还是x,说明x就是根节点if(x == this->parent[x]) return x;// 否则继续找return findParentNode(this->parent[x]);
}

2.2、并查集——合并两个并查集分量(合并两棵树)

有些时候我们需要将一些并查集分量进行合并,以满足需求
在这里插入图片描述
将根节点为 2 的树 合并到 根节点 为 1 的树上。
合并完成后 ,根节点 2 的父节点 不再是 2 了,而是 1,如下
在这里插入图片描述
再合并之前我们还需要判断一些 需要合并的两个节点是否是同一个并查集分量(同一棵树上)
代码如下:

void DisjointSets::unionSetNode(int x,int y){// 先分别获取到 x 节点和 y节点 所属树的根节点int root_x = this->findParentNode(x);int root_y = this->findParentNode(y);// 如果两个节点的根节点相等,就不需要合并,是同一颗树的节点if(root_x == root_y) return;// 如果不相等,由于是y所属树合并到 x所属树上// 所以让 y所属树的根节点的父节点赋值为x所属树的根节点this->parent[root_y] = root_x;// 同时, 此时森林少了一颗树--this->count;
}

2.3、并查集查找根节点优化——路径压缩算法

那么什么叫路径压缩内,我们先看看传统寻找某个节点所属树的根节点方法
在这里插入图片描述
相当于,我们 4 所属树根结点,要遍历所可走路径。
如果我们只做一次还好,但是如果我们要重复寻找 4 的根节点,那是不是每次都要重复走一次,显得很浪费时间,所以,我们找到了一次 4 的根节点信息,直接用类似于备忘录的思想,把 4的父节点由3直接提升为1,这样子下次找就不用老是重复遍历了
在这里插入图片描述
代码如下:

int DisjointSets::findParentNode(int x){// 路径压缩改良版的查找// 如果 x的父节点是本身,说明x是根节点,退出循环,返回xwhile( x != this->parent[x] ){// 将 x 的父节点赋值为 x的父节点的父节点this->parent[x] = this->parent[this->parent[x]];// 改变此时x的值为 x的父节点x = this->parent[x];}return x;
}

下面可以来两道leetcode的题目练练手
547. 省份数量
839. 相似字符串组

两道题的代码答案分别是:

class Solution {
public:const static int N = 205;int parent[N];int count = 0;// 查找 x 的根结点int find(int x){return x==parent[x]?x:find(parent[x]);}// 合并,把 y 合并到 x内void megre(int x,int y){int root1 = find(x);int root2 = find(y);// 判断 x与y 是否位于同一个并查集分量内,是就返回,不需要合并if(root1 == root2) return;// y的根结点的父亲更新为x的根结点parent[root2] = root1;// 合并成功说明少了一个点--count;}// 初始化并查集数据void init(int n){// 所有点的根结点初始默认是本身for(int i=0;i<n;++i)parent[i]=i;// 初始count大小就是ncount = n;}// 并查集的 第一题 实战int findCircleNum(vector<vector<int>>& isConnected) {int n = isConnected.size();// 初始化并查集init(n);for(int i = 0;i<n;++i){for(int j=0;j<n;++j){if(isConnected[i][j]==1){megre(i,j);}}}return count;}
};
class Solution {
public:const static int N = 301;int parent[N];int count=0;/// 路径压缩int find(int x){while(x != parent[x]){parent[x] = parent[parent[x]];x = parent[x];}return x;}void union_set(int x,int y){int r1 = find(x);int r2 = find(y);if(r1==r2) return;parent[r2]=r1;--count;}void init(int n){count = n;for(int i=0;i<n;++i)parent[i]=i;}bool judge(string &s1,string &s2){int k = 0;for(int i=0;i<s1.size();++i)if(s1[i]!=s2[i])++k;if(k<=2) return true;else return false;}// 考查并查集int numSimilarGroups(vector<string>& strs) {int n = strs.size();init(n);for(int i=0;i<n;++i)for(int j=i+1;j<n;++j)if(judge(strs[i],strs[j]))union_set(i,j);return count;}
};

http://chatgpt.dhexx.cn/article/7MIiNWpH.shtml

相关文章

Java——并查集

概念 当我们将多个元素分配到不同的集合中&#xff0c;这些集合有的是相关的&#xff0c;有的是不相关的。并查集就是用来查找两个元素是否在同一个集合中的 其主要实现方式是&#xff1a;将所有的元素以下标的形式存储在数组中。例如一共有十个人&#xff0c;那么就将这些人…

并查集Python版

以下来自于leetcode 使用数据结构&#xff1a;并查集 思路&#xff1a;由于相等关系具有传递性&#xff0c;所有相等的变量属于同一个集合&#xff1b;只关心连通性&#xff0c;不关心距离&#xff0c;因此很容易想到并查集。&#xff08;很容易嘛&#xff0c;反正我想不到&am…

并查集详解

文章目录 并查集一、简介1.定义2. 并查集的实现与优化 二、练习1.合并集合2.连通块中点的数量3. 食物链 三、总结 并查集 一、简介 1.定义 并查集是一种树型的数据结构&#xff0c;用于处理一些不相交集合的合并及查询问题&#xff08;即所谓的并、查&#xff09;。比如说&am…

带权并查集

带权并查集需要先理解一般的并查集&#xff0c;不明白的可自行先搜索有关内容 一般的并查集主要记录节点之间的链接关系&#xff0c;而没有其他的具体的信息&#xff0c;仅仅代表某个节点与其父节点之间存在联系&#xff0c;它多用来判断图的连通性&#xff0c;如下图所示&…

并查集,不就一并和一查?

什么是并查集 并查集这种数据结构&#xff0c;可能出现的频率不是那么高&#xff0c;但是还会经常性的见到&#xff0c;其理解学习起来非常容易&#xff0c;通过本文&#xff0c;一定能够轻轻松松搞定并查集&#xff01; 对于一种数据结构&#xff0c;肯定是有自己的应用场景和…

数据结构——并查集

并查集是一种数据结构&#xff0c;是树的一种应用&#xff0c;用于处理一些不交集&#xff08;一系列没有重复元素的集合&#xff09;的合并以及查询问题。并查集支持如下操作&#xff1a; 查询&#xff1a;查询某个元素属于哪个集合&#xff0c;通常是返回集合内的一个“代表…

并查集详解(C/C++)

并查集算法详解&#xff08;C&#xff09; 并查集基础并查集是什么&#xff1f;并查集的作用是什么&#xff1f;并查集的结构合并查询 代码实现优化1&#xff1a;避免退化&#xff08;按秩合并&#xff09;代码优化 优化2&#xff1a;路径压缩代码优化 最终代码实现复杂度分析经…

并查集及其应用

并查集的基本操作: 1.合并两个集合 2.查询两个元素的祖宗节点 扩展: 1.记录每个集合的大小 将集合大小绑定到代表元素节点上 就是并查集的思想 (不是每个元素都是正确的 但是代表元素是正确的) 2.记录每个点到根节点的距离 绑定到每个元素身上 因为每个元素到根节点的距离…

并查集(Union-Find) (图文详解)

文章目录 并查集基础知识定义C实现优化 精选算法题(Java实现)实现并查集交换字符串中的元素最长连续序列 - 字节面试常考连通网络的操作次数最大岛屿数量 (三种解法)省份数量冗余连接冗余连接Ⅱ情侣牵手(困难)移除最多的同行或同列石头等式方程的可满足性 结语 并查集基础知识 …

什么是 “并查集” ?

导语&#xff1a;并查集是一种精巧的算法&#xff0c;本身并不难理解&#xff0c;却很常用&#xff0c;在许多场景下都能找到并查集的身影。 本文作者封承成&#xff0c;年仅12岁&#xff0c;非常感谢他的投稿。 并查集是什么 并查集&#xff0c;是一种判断“远房亲戚”的算法。…

并查集(Disjoint Set)

目录 ❤️什么是并查集&#xff1f; &#x1f3b6;实现方法1 &#x1f414;实现方法2 &#x1f383;题目1 ❤️什么是并查集&#xff1f; 并查集是一种数据结构&#xff0c;用于处理一些不交集&#xff08;Disjoint sets&#xff0c;一系列没有重复元素的集合&#xff09;的…

并查集

参考 https://www.cnblogs.com/asdfknjhu/p/12515480.html https://www.bilibili.com/video/BV13t411v7Fs?p3 https://leetcode-cn.com/problems/number-of-provinces/solution/python-duo-tu-xiang-jie-bing-cha-ji-by-m-vjdr/ 一、基本概念 并查集是一种数据结构 并查集这…

并查集(详细解释+完整C语言代码)

目录 1概论 2.树的表现形式 3.代码实现 3.1创立集合 3.2合并 3.3查询 3.4路径压缩 第一个方法&#xff1a;查找时优化 第二个方法&#xff1a;合并时优化&#xff08;加权标记法&#xff09; 4.完整代码 4.1优化前 4.2优化后 1概论 并查集是一种十分精巧且实用的树形…

时间序列预测的一般步骤

一、ARIMA模型概述 ​​ ARMA模型就是AR和MA的简单结合&#xff0c;同时包含了历史数值项和错误项。由于AR和MA模型都对时间序列有平稳性要求&#xff0c;ARMA模型也存在这个限制&#xff0c;因此我们将其拓展到ARIMA模型&#xff0c;其可以解决非平稳性问题。引入的差分概念是…

时间序列预测算法总结

时间序列算法 time series data mining 主要包括decompose&#xff08;分析数据的各个成分&#xff0c;例如趋势&#xff0c;周期性&#xff09;&#xff0c;prediction&#xff08;预测未来的值&#xff09;&#xff0c;classification&#xff08;对有序数据序列的feature提…

基于深度学习的时间序列预测

# 技术黑板报 # 第十一期 推荐阅读时长&#xff1a;15min 前言 时间序列建模历来是学术和工业界的关键领域&#xff0c;比如用于气候建模、生物科学和医学等主题应用&#xff0c;零售业的商业决策和金融等。虽然传统的统计方法侧重于从领域专业知识层面提供参数模型&#xff0…

预测类问题中的时间序列预测模型

前言&#xff1a;时间序列预测模型适用于含有时间变量的模型预测&#xff0c;对中短期的预测有着较好的结果&#xff0c;对长期预测不适用。本文重点介绍ARIMA模型的原理及代码实现。 其他模型总结&#xff1a;​【Python】Python中的经典时间序列预测模型总结_风度78的博客-C…

Transformer 在时间序列预测中的应用

2017年&#xff0c;Google的一篇 Attention Is All You Need 为我们带来了Transformer&#xff0c;其在NLP领域的重大成功展示了它对时序数据的强大建模能力&#xff0c;自然有人想要把Transformer应用到时序数据预测上。在Transformer的基础上构建时序预测能力可以突破以往的诸…

【推荐收藏】11种比较常用的时间序列预测模型

时间序列及其预测是日常工作中建模&#xff0c;分析&#xff0c;预测的重要组成部分。 本文我们将从0开始介绍时间序列的含义&#xff0c;模型及其分析及其常用的预测模型。 文章目录 交流时间序列定义时间序列预测模型与方法原始数据朴素法简单平均法移动平均法指数平滑法一次…

时间序列预测的20个基本概念总结

1、时间序列 时间序列是一组按时间顺序排列的数据点 比如&#xff1a; 每小时的气压每年的医院急诊按分钟计算的股票价格 2、时间序列的组成部分 时间序列数据有三个主要组成部分。 趋势季节性残差或白噪声 3、趋势 在时间序列中记录的长期缓慢变化/方向。 4、季节性 …