数据结构(九)---并查集

目录

1.集合

2.集合的相关操作

(1)查(Find):

•Find操作的优化

(2)并(Union):

•Union操作的优化


1.集合

数据元素之间的逻辑关系可以为集合,树形关系,线性关系,图关系。对于集合而言,一个集合可以划分为若干个互不相交的子集。在集合下,两个元素之间的关系只有两种,即从属于同一个子集或从属于不同子集。

那么怎么表示这样的关系呢?在讲解森林时,提到过森林的概念,即互不相交的树的集合,那么在这里,我们可以把不同子集的元素放到不同的树中表示。

2.集合的相关操作

并查集(Disjoint Set)是逻辑结构,也就是对集合的一种具体实现,只进行“并”和“查”两种基本操作。

(1)查(Find):

•要想找到某一个元素属于哪一个集合,可以从指定元素出发,一路向上找到其唯一对应的根节点(有几个根节点,就有几棵树,就有几个集合)

在树的存储结构中,我们讲了双亲表示法,孩子表示法,孩子兄弟表示法,用哪种方法表示集合比较合适呢?

因为在集合中,需要向上找到根节点,显然使用双亲表示法更加方便。即,用一个静态数组,就能表示出父子的关系。忘记了可以看看:树

例如下图,元素L的数组下标是11,其父节点为数组下标为4的元素,即E,如此推上去,直到推到数组下标为0的元素,就是根节点了。

① 初始化并查集,将各个元素初始化为各自独立的子集。

#define SIZE 13
int UFSets[SIZE];    //集合元素数组//初始化并查集
void Initial(int s[]){for(int i=0;i<SIZE;i++)s[i]=-1;
}

② 查操作

// Find 操作,找 x 所属集合(返回 x 所属根结点)
int Find(int s[], int x) {while (s[x] >= 0)x = s[x];    // 循环寻找 x 的根return x;    // 返回根节点的下标
} 

时间复杂度:

对于下图,如果想查找J元素所属的集合,只需要向上找一次就可以找到根节点。

但是对于下图,就需要向上找很多层,才能找到根节点。

所以,若节点数为n,Find最坏时间复杂度为O(n),可以看到Find最坏时间复杂度与高度h直接相关,所以优化并查集的效率时,可以在合并树时减小树的高度。这一点留到“合并树”的时候讲。

•如果想判断两个元素是否属于同一个集合,那就分别查找两个元素的根节点,判断根节点是否相同。

bool Compare(int Root1, int Root2) {if (Find(Root1) == Find(Root2))return true;elsereturn false;
}
•Find操作的优化

之前使用的Find操作是从指定节点出发,根据s[ ],向上找到所属根节点,这样向上的路径称为“查找路径”,而Find的优化操作就是要压缩这条路径,即“压缩路径”。具体操作就是先找到根节点,再将查找路径上所有结点都挂到根结点下

例如下图,是执行节点L的查找路径:

压缩路径就是将图中蓝色的节点全部挂到A节点下。这样,从L节点向上找根节点的路径就被压缩了。

优化代码如下:

//Find"查"操作优化,先找到根节点再进行"压缩路径"
int Find(int S[],int x){int root = x;while(S[root]>=0)    root=S[root];  //循环找到根while(x!=root){ //压缩路径int t=S[x];    //t指向x的父节点S[x]=root;   //x直接挂到根节点下 x=t;}return root;    //返回根节点编号
}

每次 Find 操作,先找根,再“压缩路径”,可使树的高度不超过O(\alpha(n))\alpha(n)是一个增长很缓慢的函数,对于常见的n值,通常\alpha(n)≤4,因此优化后并查集的Find、Union操作时间开销都很低。

具体地,Find最坏时间复杂度O(\alpha (n))将n个独立元素通过多次Union合并为一个集合的最坏时间复杂度为O(n*\alpha (n))(n个元素需要合并n-1次)。

(2)并(Union):

•要想将两个集合“并”为同一个集合,可以将一棵树作为另外一棵树的子树。

//Union"并"操作,将两个集合合并为一个
void Union(int s[],int Root1,int Root2){//要求Root1与Root2是不同的集合if(Rootl==Root2)    return;//将根Root2连接到另一根Root1下面S[Root2]=Root1;
}
//时间复杂度:O(1)

S[Root2]=Root1达到的效果如下(假设要将以C为根节点的树合并为以A为根节点的子树):

刚开始Root1 = 0;Root2 = 2;将S[2]=0

也就是将C的父节点指向0号元素A

若想将n个独立元素通过多次Union合并为一个集合,最坏时间复杂度为O(n^2)。因为要合并n个独立的元素,需要n-1次Union,每一次Union之前需要从指定节点出发找到两个集合的根节点,而Find操作时间复杂度为O(n),所以重复n-1次的Union,最坏时间复杂度为O(n^2)。

•Union操作的优化

为了使“查”的效率更高,合并树时可以让小树合并到大树中,这样就不会增加树的高度了。

那么如何表示一棵树的大小呢?可以用根节点的绝对值表示树的结点总数。

例如下图2,以A为最左边树的根节点,A所对应的数组的值为-6,|-6|就是这棵树的节点总数。同理,以C为根节点的树有两个节点,以D为根节点的树有5个节点。

优化代码如下: 

//Union"并"操作,小树合并到大树
void Union(int S[],int Rootl,int Root2){if(Rootl == Root2)    return;if(S[Root2]>S[Root1]){     //Root2结点数更少    S[Root1]+= S[Root2];    //累加结点总数S[Root2]=Rootl;    //小树合并到大树} else {S[Root2]+= S[Root1];    //累加结点总数S[Root1]=Root2;    //小树合并到大树}
}
//改进的Union操作时间复杂度依旧是O(1)

用该方法优化“Union”操作后,构造的树高不超过\left \lfloor log_{2}n \right \rfloor+1,那么Find操作的最坏时间复杂度也能到O(log_{2}n),将n个独立元素通过多次Union合并为一个集合的最坏时间复杂度为O(n*log2^n)

总结:

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

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

相关文章

【嵌入式AI部署神经网络】STM32CubeIDE上部署神经网络之指纹识别(Pytorch)——篇一|环境搭建与模型初步部署篇

前言:本篇主要讲解搭建所需环境,以及基于pytorch框架在stm32cubeide上部署神经网络,部署神经网络到STM32单片机,本篇实现初步部署模型,没有加入训练集与验证集,将在第二篇加入。篇二详细讲解STM32CubeIDE上部署神经网络之指纹识别(Pytorch)的数据准备和模型训练过程等,…

Chrome 网络调试程序 谷歌网络调试 network

目录 1.网络面板总览2.概况了解3.Waterfall接口排队等待时间4.关注请求接口的Size,可能是占据内存溢出的接口5.过滤器一栏 fetch/xhr 什么意思6. Stalled 什么意思7.Queueing 什么意思8.Queueing和Stalled之间什么关系9.为什么会有阻塞状态10.Time列是pending 什么意思 1.网络面…

宏基因组|使用MEGAHIT组装

简介 MEGAHIT 是一款超快速且内存高效的下一代测序&#xff08;NGS&#xff09;组装工具&#xff0c;专门针对宏基因组进行了优化&#xff0c;同时在处理常规单个基因组&#xff08;小型或哺乳动物规模&#xff09;以及单细胞组装任务时也有出色表现。 主要特点与功能&#x…

node.js egg.js

Egg 是 Node.js 社区广泛使用的框架&#xff0c;简洁且扩展性强&#xff0c;按照固定约定进行开发&#xff0c;低协作成本。 在Egg.js框架中&#xff0c;ctx 是一个非常核心且常用的对象&#xff0c;全称为 Context&#xff0c;它代表了当前 HTTP 请求的上下文。ctx 对象封装了…

数据库和表创建练习

一丶要求 1.创建一个数据库db_classes 2 创建一行表db_hero 3. 将四大名著中的常见人物插入这个英雄表 二丶创建db_classes一个数据库, 使用数据库默认的字符集 create database db_classes; 三丶创建一行表db_hero 1.先切换到我们创建的db_classes;数据库中 use db_class…

怎么从回收站恢复已删除的文件?(5种恢复方法)

回收站是电脑操作系统中的一个特殊目录&#xff0c;用于存储被删除但尚未完全清除的文件和文件夹。当用户删除文件或文件夹时&#xff0c;它们并不立即从硬盘驱动器中移除&#xff0c;而是被移动到回收站。这样设计的目的是为了给用户一个“第二次机会”&#xff0c;如果他们意…

nvm的下载与安装

nvm&#xff08;Node Version Manager&#xff09;是一个用于管理 Node.js 版本的工具&#xff0c;它允许您在同一台计算机上安装和切换不同的 Node.js 版本。 一、下载地址 https://github.com/coreybutler/nvm-windows/releases 二、安装nvm 三、设置环境变量 在命令提示…

linux系统-FTP服务配置

目录 一、FTP简介 1.什么是FTP&#xff1f;&#xff1f;&#xff1f; 2.FTP的两种模式 二、安装配置FTP服务 1.关闭防火墙和核心防护 2.安装VSFTPD 3.修改配置文件 4.黑白名单设置 一、FTP简介 1.什么是FTP&#xff1f;&…

uniapp-css多颜色渐变:左右+上下

案例展示 案例代码&#xff1a; 代码灵感&#xff1a;使用伪类进行处理 <view class"headBox"></view>.headBox {height: 200rpx;background: linear-gradient(to right, #D3D5F0, #F0DCF3, #F7F6FB, #DAE8F2, #E1D3EE);position: relative; }.headBox…

理解归并排序的两种方法(超详细)

目录 前言 一.方法一&#xff1a;归并排序 1.1 归并思路 1.1.1 递归(分解) 1.1.2 区间(排序) 1.1.3 合并拷贝回原数组(合并) 二.归并排序过程 2.1 递归(分解)图解 2.2 归并有序区间(排序)图解 2.2.1 单独一趟排序 2.2.2 有序区间递归排序 2.2.3 数组拷贝(合并) 2.3 归并全部代码…

SpringCloud(微服务介绍,远程调用RestTemplate,注册中心Nacos,负载均衡Ribbon,环境隔离,进程和线程的区别)【详解】

目录 一、微服务介绍 1. 系统架构的演变 1 单体架构 2 分布式服务 3 微服务 2. SpringCloud介绍 SpringCloud简介 SpringCloud版本 3. 小结 二、远程调用RestTemplate【理解】 1. 服务拆分 1 服务拆分原则 2 服务拆分示例 1) 创建父工程 2) 准备用户服务 1. 用户…

Vue 组件单元测试深度探索:细致解析与实战范例大全

Vue.js作为一款广受欢迎的前端框架&#xff0c;以其声明式的数据绑定、组件化开发和灵活的生态系统赢得了广大开发者的心。然而&#xff0c;随着项目规模的增长&#xff0c;确保组件的稳定性和可靠性变得愈发关键。单元测试作为软件质量的守护神&#xff0c;为Vue组件的开发过程…

Appium一本通

Appium介绍 概念&#xff1a;Appium是一个移动App(手机应用)自动化工具。 用途&#xff1a;重复性任务、爬虫、自动化测试。 特点&#xff1a;开源免费、多平台支持(ios\android)、多类型支持(native\webview)、类selenium支持多语言(java\python\js\ruby) Appium原理 三个主…

Java中的ArrayList

ArrayList<E>的特点 可调整大小的数组实现 <E>:是一种数据类型 ArrayList的构造方法 ArrayList list new ArrayList();创建一个空的集合对象 package dayhou40.day45; ​ import java.util.ArrayList; ​ public class Arraylisttest {public static void ma…

客户端连接ZK失败处理方案

文章目录 背景介绍报错信息处理方案第一步、查看zookeeper启动是否正常第二步、检查本地网络是否正常第三步、检查本地JDK版本 对于zookeeper服务注册中心&#xff0c;在前期【 Dubbo框架注册中心-Zookeeper搭建】博客中有环境搭建部署介绍&#xff0c;感兴趣可以参考安装。 背…

python使用opencv对图像的基本操作(2)

13.对多个像素点进行操作&#xff0c;使用数组切片方式访问 img[i,:] img[j,:] #将第j行的数值赋值给第i行 img[-2,:]或img[-2] #倒数第二行 img[:,-1] #最后一列 img[50:100,50:100] #50-100行&#xff0c;50-100列&#xff08;不包括第100行和第100列&#xff09; img[:100…

SpringCloud系列(18)--将服务提供者Provider注册进Consul

前言&#xff1a;在上一章节中我们把服务消费者Consumer注册进了Zookeeper&#xff0c;并且成功通过服务消费者Consumer调用了服务提供者Provider&#xff0c;而本章节则是关于如何将服务提供者Provider注册进Consul里 准备环境&#xff1a; 先安装Consul&#xff0c;如果没有…

ElasticSearch语句中must,must_not,should 组合关系

前言&#xff1a; 在实际应用中&#xff0c;发现当bool中同时使用must和should 没有达到想要的想过&#xff0c;而是只展示了must中的命中数据&#xff0c;所以打算探究一下bool中 三种逻辑关系的组合。 上述查询语句只展示了must的结果&#xff0c;没有should中的结果&#…

yolov8旋转目标检测输出的角度转化为适合机械爪抓取的角度

1. 机械爪抓取时旋转的角度定义 以X轴正方向&#xff08;右&#xff09;为零度方向&#xff0c;角度取值范围[-90&#xff0c;90)。 确认角度的方法&#xff1a; 逆时针旋转X轴&#xff0c;X轴碰到矩形框长边时旋转过的角度记为angleX&#xff1a; 1.如果angleX小于90&#xf…

RDD编程初级实践

参考链接 spark入门实战系列--8MLlib spark 实战_mob6454cc68310b的技术博客_51CTO博客https://blog.51cto.com/u_16099212/7454034 Spark和Hadoop的安装-CSDN博客https://blog.csdn.net/weixin_64066303/article/details/138021948?spm1001.2014.3001.5501 1. spark-shell…