什么是 “并查集” ?

article/2025/8/27 2:54:30

导语:并查集是一种精巧的算法,本身并不难理解,却很常用,在许多场景下都能找到并查集的身影。

本文作者封承成,年仅12岁,非常感谢他的投稿。

并查集是什么

并查集,是一种判断“远房亲戚”的算法。

打个比方:你身边的某个“朋友”,很有可能就是你父亲的母亲的姑妈的大姨的哥哥的表妹的孙子的女儿的父亲的孙子。如果给定这么一张“家谱”(无向图),如何判断两个顶点是不是“亲戚”呢?用人话说,就是判断一个图中两个点是否联通(两个顶点相互联通则为亲戚)。

并查集是专门用来解决这样的问题的,和搜索不同,并查集在构建图的时候同时就标记出了哪个“人”属于哪个“团伙”(一团伙中的点两两联通)。

并查集的操作

1. 初始化

并查集的思想是通过标记确定该顶点所在的组

所以对于一个n个点,m条边的图,我们需要新建一个长度为n的数组f(可以理解为father),f[n]代表点n的团伙“代表人”,当两个点所在团伙“代表人”相同,则这两个点所在团伙相同。

而在最开始,每个顶点间都是互相不连通的,所以每个顶点单独属于一个团伙,每个顶点理所应当成为自己团伙的“代表人”,所以我们把f[n]的初始值赋为n。

2. 合并团伙

我们以连接3和1这两个点做例子:

在连接点3和点1时,3和1形成了一个团伙,而3和1的团伙代表人f[3]和f[1]就应该统一,具体是让3做代表人还是让1做代表人随便,我们让1做代表人。f[3] = 1,这条语句可以理解为让1所在团伙的代表人同时成为3所在团伙的代表人。

(箭头只是体现了f数组中“团伙成员”和“代表人”的关系,其实这个图是无向图)

可是,像f[a] = b这样合并真的对吗?请读者考虑这样一种情况。

刚刚我们合并了3和1,现在我们需要合并3和2。如果按照f[a] = b这样合并,那么,f[3]就被赋值为了2。这样,f[3]原本的值1就被覆盖了,也就是说,1和3的团伙就被硬生生地“拆散”了。

下面我们换一个例子:合并3和4。此时我们不应该令f[3] =4,应该让f[3的团伙代表人] = (4的团伙代表人),如下图。

这样,合并两个团伙的工作就完成了。总结起来就一句话:f[a的团伙代表人] = (b的团伙代表人)。

3. 查找团伙代表人

紧接着,又一个问题浮出水面:根据上面的公式f[a的团伙代表人] = (b的团伙代表人),可是a、b的团伙代表人怎么求?是f[a]吗?不不不,这里的情况变得复杂了。大家再次考虑一种特殊情况。

在这种情况下,3的团伙代表人是谁?1还是4?正确答案是4。因为,一个团伙中每一个点都直接或间接地“指向”这个团伙的代表人。(1,3,4)这个团伙中,1直接地指向4,3间接地指向4,所以4才是这个团伙里的代表人。

那么,点x的团伙代表人怎么求呢?我们会发现另一个特征,任何一个团伙的代表人a,都有f[a] = a。很好理解,团伙代表人也是团伙的一个成员,团伙代表人所在团伙的代表人就是它自己。

而对于其他点a,f[a]均不等于a。并且如果一个顶点a有f[a] ≠ a,那么这个点一定不是团伙的代表人,因为f[a]不会间接地或直接地指向a(并查集保证不会存在环)。

根据这一特性,我们可以判断点a是否为某个团伙的代表人。

在例子中,我们想要知道1是否为团伙代表人,就可以看f[1]是否等于1,很明显,f[1] = 4,所以1不是该团伙的代表人,我们要继续“追本溯源”,对5进行判断。这个过程就是一种递归的寻找过程。

知道了这个特性,我们就可以写出相应的C++代码(这里还给出了循环版的代码,根据情况使用):

int getFather(int x) {return f[x] == x ? x : getFather(f[x]);
}
int getFather(int x) {while (f[x] != x)x = f[x];return x;
}

这是一个递归函数,如果f[x] = x,说明这个点已经是该团伙的代表人,直接返回就好了,如果它不是该团伙的代表人,那么就返回自己指向的点的团伙代表人。

在求getFather(3)时,f[3] != 3,返回getFather(f[3])也就是getFather(1);

在求getFather(1)时,f[1] != 1,返回getFather(f[1])也就是getFather(4);

在求getFather(4)时,f[4] == 4,返回4。递归结束。最后计算出3的团伙代表人是4。

4. 查询顶点是否在同一团伙

并查集的最后一种操作叫做查询,就是查询两个点是否连通(在同一团伙)。

前面已经讲了,当两个点所在团伙“代表人”相同,则这两个点所在团伙相同。判断两个点a、b在同一团伙的方法就是:

getFather(a) == getFather(b) 

5. 完整代码

const int N = 100; // 节点数量
int f[N];int init() {// 初始化for (int i=0; i<N; i++)f[i] = i;
}int getFather(int x) {// 查询所在团伙代表人return f[x]==x ? x : getFather(f[x]);
}int merge(int a, int b) {// 合并操作f[getFather(a)] = getFather(b);
}bool query(int a, int b) {// 查询操作return getFather(a) == getFather(b);
}int main() {init();merge(3, 1); // 3和1是亲戚merge(1, 4); // 1和4是亲戚cout << getFather(3) << endl; // 输出3的团伙代表人+换行cout << query(3, 1) << endl; // 输出3和1是否是亲戚+换行
}

并查集巧妙吧!我们既没有构建图,也没有构建边,自始至终只用到了f数组,又优化了时间。

不要小瞧并查集代码短,在很多时候并查集都会派上用场,比如著名的克鲁斯卡尔算法,就是通过并查集判断两个顶点是否相连的。更重要的是体会并查集的思想,用这种思想来优化代码。

好了,今天的并查集就介绍到这里,希望大家能好好消化吸收,欢迎点个在看哦~~

—————END—————

喜欢本文的朋友,欢迎关注公众号 程序员小灰,收看更多精彩内容

点个[在看],是对小灰最大的支持!

http://chatgpt.dhexx.cn/article/qxF2WMaP.shtml

相关文章

并查集(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、季节性 …

时间序列-预测(Forcasting):时间序列预测算法总结

一、背景介绍 绝大部分行业场景,尤其是互联网、量化行业,每天都会产生大量的数据。金融领域股票价格随时间的走势;电商行业每日的销售额;旅游行业随着节假日周期变化的机票酒店价格等; 我们称这种不同时间收到的,描述一个或多种特征随着时间发生变化的数据,为时间序列…

时间序列预测 | ARMA应用指南

ARMA可谓是时间序列最为经典常用的预测方法&#xff0c;广泛应有于涉及时间序列的各个领域。ARMA模型自出道以来&#xff0c;出场次数不可胜数。想必大家也都不陌生&#xff0c;常学常新&#xff0c;我们今天不妨再来回顾一遍&#xff5e;。 ARMA全称Autoregressive moving ave…

时间序列预测的7种方法

import pandas as pd#取数 #dfpd.read_csv(jetrail.csv) #print(df.head()) ID Datetime Count 0 0 25-08-2012 00:00 8 1 1 25-08-2012 01:00 2 2 2 25-08-2012 02:00 6 3 3 25-08-2012 03:00 2 4 4 25-08-2012 04:00 2#pr…

Transformer时间序列预测

介绍&#xff1a; 提示&#xff1a;Transformer-decoder 总体介绍 本文将介绍一个 Transformer-decoder 架构&#xff0c;用于预测Woodsense提供的湿度时间序列数据集。该项目是先前项目的后续项目&#xff0c;该项目涉及在同一数据集上训练一个简单的 LSTM。人们认为 LSTM 在…

时间序列预测的8种常用方法简介

时间序列预测的7种方法 1. 朴素预测法&#xff08;Naive Forecast) 如果数据集在一段时间内都很稳定&#xff0c;我们想预测第二天的价格&#xff0c;可以取前面一天的价格&#xff0c;预测第二天的值。这种假设第一个预测点和上一个观察点相等的预测方法就叫朴素法&#xff…

常见的时间序列预测模型python实战汇总

最完整的时间序列分析和预测&#xff08;含实例及代码&#xff09;&#xff1a;https://mp.weixin.qq.com/s/D7v7tfSGnoAqJNvfqGpTQA 1 时间序列与时间序列分析 在生产和科学研究中&#xff0c;对某一个或者一组变量 x(t)x(t) ARIMA 模型对时间序列的要求是平稳型。因此&#…

时间序列预测模型

时间序列数据一般有以下几种特点&#xff1a;1.趋势(Trend) 2. 季节性(Seasonality)。 趋势描述的是时间序列的整体走势&#xff0c;比如总体上升或者总体下降。下图所示的时间序列是总体上升的&#xff1a; 季节性描述的是数据的周期性波动&#xff0c;比如以年或者周为周期&…

【数据分析】基于时间序列的预测方法

时间序列预测 目录 时间序列预测1.时间序列介绍2.原始数据集3.导入数据4.检测时间序列的平稳性5.如何使时间序列平稳5.1 估计和消除趋势5.1.1 对数转换5.1.2 移动平均 5.2 消除趋势和季节性5.2.1 差异化5.2.2 分解 6.预测时间序列6.1 AR Model6.2 MA Model6.3 Combined Model6.…

Matlab实现时间序列预测

文章目录 一、数据准备二、时间序列预测分类1、输入为xt&#xff0c;输出是yt2、有x值&#xff0c;有y值&#xff1a;NARX(1)选择模型类型(2)选择输出&#xff0c;只有y_t(3)选择70%用来作为训练数据&#xff0c;15%用来作为验证使用&#xff0c;15%用来测试(4)选择delay(5)开始…

【时序预测】Transformer模型在时间序列预测领域的应用

今天又是一篇Transformer梳理文章&#xff0c;这次应用场景是时间序列预测。Transformer的序列建模能力&#xff0c;让其天然就比较适合时间序列这种也是序列类型的数据结构。但是&#xff0c;时间序列相比文本序列也有很多特点&#xff0c;例如时间序列具有自相关性或周期性、…