13-并查集

2023-11-16

数据结构并查集常用于将两个集合并起来以及查询两个元素是否隶属于同一个集合。相对于传统我们的求法,并查集算法极大减少了查询的工作量,提高了效率。

合并集合

假设我们有两个集合,常规情况下合并两个集合就是将它们混合起来:

但是在计算机中,如果我们想要合并两个集合,那么我们应该怎么做呢?这里合并集的数据结构提供了一种方法:将集合里的元素先按树状结构存储好,然后再在每一个集合中找到树根元素,将树根和另一个树根连起来就可以将两个集合合并成一个集合。下面就是两个集合未合并前按照树状结构排好的样子:

蓝色表示大集合1,粉色表示大集合2,现在我们想要将两个集合合成一个集合,只需要将粉色集合根元素连到蓝色集合根元素或者将蓝色集合根元素连到粉色集合根元素(粉色集合作为蓝色集合的分支或者蓝色集合作为粉色集合的分支)即可:

如果具体落实到代码,在形成两个大集合之前首先得有每一个小集合(大集合对应粉色集合/蓝色集合,小集合代表单独或多个粉色/蓝色元素形成的元素)。为了将集合连接起来,首先我们需要创建一个数组pre,这个数组里的每一个元素将会负责存储该元素的上级的位置,并且初始时需要对该数组进行初始化,初始化时每个元素都是一个集合,所以它们的pre数组存储的都是本身的下标。

#include<iostream>

using namespace std;

const int N = 100;
int pre[10];

void init()
{
	//初始化
	for (int i = 0; i < 10; i++)
	{
		pre[i] = i;
	}
}

下图1为初始状态,每个字母元素都代表自己一个集合,此时pre数组存储内容如下:

如果分别将上面的小集合合并成两个大集合,那么合并后的集合假设是下面的样子:

 此时pre数组下标将变成:

pre数组里面存储的就是每个元素的上级的坐标。而合并两个集合就是将一个元素例如合并A和B,那么我们只需要将A的上级指定为B,即令pre[4]=2。由此我们可以推出,合并两个集合的抽象操作具体到函数Com就对应就着修改pre数组的操作:

void Com(int x, int y)
{
	pre[find(x)] = find(y);
}

这里的find函数我们先按下不表,我们只需要知道它的意义是找到当前集合的根元素的下标就可以了,所以Com函数的操作就相当于将一个集合的根元素连接到另一个集合上的某一个元素中(常连到另一个集合的根元素上):

查询元素

上面我们接触到了find函数,这个函数就是用于查找某个元素A是否属于某个集合B,查找的过程就是根据要比较的元素A找到该元素所属的集合A的根元素C,再和集合B的根元素D进行对比,如果C和D是同一个元素,那么它们就来自同一个集合,反之则不是。所以查询元素的过程就是在树状结构中不断往上找根元素的过程,我们知道pre数组存储的是某个元素的上级的下标,那我们只需要不断循环往上找,当找到那个下标就是它本身那就代表它是根元素。对到代码就是:

int find(int x)
{
    while(x!=pre[x])
        x=pre[x];
	if (pre[x] == x) return x;
}

这里pre[X]==X就是找到了根元素,返回根元素的下标,要是找到的不是根元素,那么我们就让x等于它的上级下标,即继续向上找。这里我们可以优化一下,既然每次都向上层层找根元素这么麻烦,那么我们为什么不一步到位直接将要找的元素和根元素连在一起,这样就可以直接避免中间又要一步步找其它上级的过程:

将这个过程对应到代码就是使用一个递归过程,让每一次x寻找上级都变成寻找根即可:

int find(int x)
{
	if (pre[x] == x) return x;
	else return pre[x] = find(pre[x]);
}

参考资料:

参考资料1

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

13-并查集 的相关文章

  • rosrun 和 roslaunch 的时候 TAB 的自动补全出现问题

    rosrun 和 roslaunch 的时候 TAB 的自动补全出现问题 rospack Warning error while crawling home sun boost filesystem status Permission de
  • javaRebel(jRebel)使用手记

    想必大家对项目开发中 调试类文件修改时 容器自动重新加载漫长的过程早已厌倦 我今天闲来无事 于是 想试试javaRebel jRebel 这个东西 javaRebel jRebel 现在是收费软件 不过在网上可以下载到确解版的 在网上查了一

随机推荐

  • please remember me(auto login)

    记住我 用户自动登录的实现 auto login 一 什么是用户自动登录 对于我们的网站向已注册用户提供某些专门的服务 比如网上购物 在线下载 收费浏览等等 就会要求用户在使用这些服务之前进入登录页面 输入用户名和密码 并进行验证 如果用户
  • 搜索引擎(简化版)-分析总结

    整体思路 访问网址 进入首页 输入搜索内容 HTTP服务器接收到HTTP响应 解析取出其中的搜索内容 将搜索内容传输给CGI程序 既搜索客户端 由搜索客户端将搜索内容构造成一个请求 发送给搜索服务器 搜索服务器将请求解析 将搜索内容进行分词
  • hello_Makefile_c++

    1 错误 hello o In function start text 0x0 multiple definition of start usr lib gcc i486 linux gnu 4 4 3 lib crt1 o text 0x
  • html锚点反向联动,Vue监听滚动实现锚点定位(双向)示例_苏颜_前端开发者

    在项目需求中需要实现一个滚轴联动锚点的功能 效果图如下 功能代码demo如下 item name item export default data return scroll list name 第一条 backgroundcolor 90
  • MIPI DSI协议解析

    今天我们一起来学习一下MIPI DSI协议 1 Overview DSI 全称Display Serial Interface 是由MIPI联盟定义的处理器与外设之间的移动设备接口规范 该规范建立在现有的标准的基础上 并采用了MIPI联盟D
  • 从数据库导出List<Map>数据动态生成sheet(数据量少可以参考看看)

    有个问题要注意 数据库导出Map数据如果值为空 这个字段和值不会查询出来 因为我上面配置没成功 execl列名 我用的是sql中文别名截取 就不用创建实体类了 如果你上面没问题就忽略 第一步POM文件
  • arcTo方法理解

    arcTo方法理解 arcTo方法有五个参数 ctx arcTo x1 y1 x2 y2 radius arcTo的参数中包括两个点 x1 y1 x2 y2 radius半径 起点和第一个控制点组成的延长线与第一个控制点和第二个控制点组成的
  • QT笔记- 排序函数qSort()基本用法

    函数 qSort 函数是Qt的一个全局函数 但已被弃用 使用sort 可代替 其原型如下 template
  • 字符串数组反转输出 以空格为单词分隔符 C++

    给出字符串数组及其长度 字符串有若干单词和空格组成 下边代码将数组中单词反转输出 输入 Welcom to Hubei Wuhan 输出为 Wuhan Hubei to Welcom 代码思路为 1 定义两个指针 分别指向一个单词的开头和结
  • 常用终止goroutine的方法

    var wg sync WaitGroup func foo defer wg Done for fmt Println 我是foo函数内的Print time Sleep time Millisecond 500 func main wg
  • 十问了解人工智能

    一 什么是人工智能 人工智能 Artificial Intelligence 简称AI 是指通过计算机技术实现的智能行为 这种行为可以表现为感知 推理 学习 理解 交互等能力 它是一种技术和科学 旨在让计算机能够像人类一样思考 决策和行动
  • Kali linux安装中文输入法

    kali安装中文输入法 pinyin 以下所有步骤在root和update更新后执行 首先安装ibus到系统里 所有指令复制即可使用 apt get install ibus ibus pinyin 安装时会选择是否继续 输入y或者yes即
  • Flask学习

    flask 1 py from flask import Flask app Flask name app route def index return h1 hello world h1 app run flask 2 py from f
  • 基于Pygame的兔獾大战游戏的设计与实现_kaic

    当今社会是一个信息社会且时代发展迅速 时代发展迅速伴随而来的是越来越大的压力 所以通过游戏解压的需求越来越大 游戏也逐渐成为人们日常的娱乐方式 兔獾大战游戏设计了简单的游戏界面和容易让用户理解的游戏操作方式 使得用户可以更好的进行游戏体验
  • C++中的函数模板

    觉得大神写的很好 就摘抄下来了 有需要可以查看原版链接 如下 以下内容是摘抄博客 C 中的函数模板 年少轻狂 幸福时光 CSDN博客 函数模板 之前我们知道的交换两个变量的方法有宏定义 函数 这两种方式都能实现两个变量的交换 但是各有各的优
  • Ubuntu镜像下载地址

    镜像地址https launchpad net ubuntu cdmirrors
  • Tomcat集群配置

    1 Tomcat集群 多个 Tomcat 服务器构成了一个集群 Cluster 系统 共同为客户提供服务 集群系统具有以下优点 高可靠性 高性能计算 负载平衡 图1 1显示了由 JK插件和两个 Tomcat服务器构成的集群系统 集群系统的正
  • Jeesite 过滤指定字典的值(显示字典的一部分值)

    一 HTML div class form group div
  • uni/vue transition不生效的解决办法

    uni中目前还是使用vue2 自上而下的过渡效果 从底部飞入 fly in from bottom 进入过渡生效 离开过渡生效 enter active leave active transition transform 3s enter
  • 13-并查集

    数据结构并查集常用于将两个集合并起来以及查询两个元素是否隶属于同一个集合 相对于传统我们的求法 并查集算法极大减少了查询的工作量 提高了效率 合并集合 假设我们有两个集合 常规情况下合并两个集合就是将它们混合起来 但是在计算机中 如果我们想