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

article/2025/8/27 0:21:18

并查集算法详解(C++)

  • 并查集基础
    • 并查集是什么?
    • 并查集的作用是什么?
    • 并查集的结构
      • 合并
      • 查询
    • 代码实现
      • 优化1:避免退化(按秩合并)
        • 代码优化
      • 优化2:路径压缩
        • 代码优化
    • 最终代码实现
    • 复杂度分析
    • 经典例题
      • 并查集入门
      • Wireless_Network
  • 并查集进阶1:带权并查集
    • 带权并查集是什么?
    • 带权并查集的作用是什么?
    • 经典例题
      • The_Suspects
  • 并查集进阶2:种类并查集
    • 种类并查集是什么?
    • 种类并查集的作用是什么?
    • 经典例题
      • 食物链
      • 关押罪犯

并查集基础

并查集是什么?

并查集是用来管理元素分组的算法。

并查集的作用是什么?

并查集可以高效的对元素进行分组(合并在一起),并且能快速的查询两个元素是否属于同一组。

并查集的结构

合并

并查集是一种树状结构。比如元素1和2属于同一组、元素1和3也属于同一组,那么元素2和3能通过元素1合并为同一组,即元素1为元素2和3的老大,那么元素1就是元素2和元素3在树状结构中的根。

在这里插入图片描述

当许多组元素需要合并在一起时,只需将各组元素的老大合并在一起即可,也就是让其中一个根指向另一个根,就使得两棵树合并成了一棵树,也就把两个组合并为了一个组。

在这里插入图片描述

查询

当我们要查询两个元素是否属于同一个组时,我们需要沿着各个节点往上向树的根进行查询,如果最终发现两个元素的根相同,那么他们就属于同一个组。反之,则不属于同一个组。

在这里插入图片描述
如图中:元素2和3的根都为元素1,故他们属于同一个组;元素2和7,他们的根分别为元素1和5,不同,故他们不属于同一个组。

代码实现

int f[maxn]; //全名为 father,父节点的意思//初始化 n个元素 
void Init() {//使每个元素的根节点是其本身//即初始时每个元素都是单独的 for(int i=1; i<=n; i++) f[i]=i;  
}
//查询树的根
//非递归实现
int Find(int i) {while(f[i] != i) {  //直到元素的父节点是它本身,表示已经查询到了树的根i = f[i];return i; 			//返回根节点对应的元素 
}//递归实现
int Find(int i) {if(f[i]==i)      //若元素的根节点为其本身,那么此元素就是树的根 return f[i];    //直接返回元素本身即可elsereturn Find(f[i]); //否则继续查询,知道查询到树的根位置 
}//简化版
int Find(int i) {return f[i]==i ? f[i] : Find(f[i]);
} 
//合并
void merge(int a, int b) {//先找到两个元素对应的根对应的元素 int fa = Find(a); int fb = Find(b);if(fa==fb) return;else f[fa]=fb;  //否则令元素 a的根指向元素 b的根 
} //简化版
void merge(int a, int b) {f[Find(a)] = Find(b);
} 

优化1:避免退化(按秩合并)

因为并查集的结构是树状结构,所以需注意退化问题。避免退化发生的方法如下:
首先,我们合并时,可记录这棵树的高度(记为rank)。接下来当我们需合并两棵树时,我们先对两棵树的高度进行判断,如不同,则让高度小的树的根指向高度大的根。如下图:
在这里插入图片描述

代码优化

对初始化(Init)函数和合并(merge)函数进行优化

//初始化优化
int f[maxn];
int h[maxn]; //全名为 heightvoid Init() {for(int i=1; i<=n; i++) {f[i] = i;h[i] = 0;  //令每棵树的高度初始值都为 0 }
} 
//合并优化
void merge(int a, int b) {int fa = Find(a);int fb = Find(b);if(fa==fb) return; if(h[fa] < h[fb]) {  //如果元素 a对应的树的高度比 b小 f[fa] = fb;  //使元素 a的根指向元素 b的根 } else {f[fb] = fa;  //否则让元素 b的根指向元素 a的根 if(h[fa] == h[fb]) h[fa]++;// 如果两者对应的树的高度相同,则使新生成的树高度 +1 }
}

PTA L2-024 部落 (25 分)
在这题中,若不对merge进行优化就会运行超时

优化2:路径压缩

由于查询时我们需沿着元素所在的树从下往上查询,最终找到这棵树的根,表明这个元素与其根对应元素属于同一组。因为在此查询过程中我们会经过许多节点,而如果我们能将这个元素直接指向根节点,那么就能节省许多查询的时间。同时,在查询过程中,每次经过的节点,我们都可以同时将他们一起直接指向根节点。这样做的话,我们再查询这些节点时,就能很快知道他们的根是谁了。
在这里插入图片描述

代码优化

对查询(Find)函数进行优化

//查询优化
int Find(int i) {return f[i]==i ? f[i] : f[i] = Find(f[i]);//使元素直接指向树的根 
} 

最终代码实现

void Init() {for(int i=0; i<=n; i++) {f[i] = i;h[i] = 0;}
}
int Find(int i) {return f[i]==i ? f[i] : f[i]=Find(f[i]);
}
void merge(int a, int b) {int fa = Find(a);int fb = Find(b);if(fa != fb) {if(h[fa] < h[fb]) {f[fa] = fb;} else {f[fb] = fa;if(h[fa] == h[fb]) h[fa]++;}}
}

复杂度分析

经过两个优化后,并查集的效率变得非常高。对n个元素的并查集进行一次操作的均摊复杂度是O(a(n)) (a(n)是阿克曼函数的反函数),比优化前的O(log(n))还要快。

经典例题

并查集入门

Wireless_Network

并查集进阶1:带权并查集

带权并查集是什么?

带权是指一个元素具有额外的信息。比如元素1对应着数值6,元素2对应着数值4。这些带有信息的元素组成的并查集即为带权并查集。

带权并查集的作用是什么?

带权并查集能计算各个小组中元素的个数、能计算n个元素中还有几个元素没有加入小组中;计算分数、距离等等

注释:带权并查集需要在路径优化的基础下进行。

经典例题

The_Suspects

并查集进阶2:种类并查集

种类并查集是什么?

种类并查集是能把并查集分为几个部分,每个部分的种类不同。

种类并查集的作用是什么?

种类并查集能将两个阵容分开。比如把好人和坏人分为两个阵营。

经典例题

食物链

关押罪犯

参考资料:
《挑战程序设计竞赛》
路径压缩_并查集


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

相关文章

并查集及其应用

并查集的基本操作: 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、季节性 …

时间序列-预测(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;比如以年或者周为周期&…