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

news2024/10/6 10:35:48

目录

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;
    else
        return 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.coloradmin.cn/o/1627460.html

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

相关文章

微信小程序:8.WXSS

WXSS和CSS的关系 WXSS具有CSS大部分特性&#xff0c;同时&#xff0c;WXSS还对CSS进行扩充以及修改&#xff0c;适应微信小程序的开发。 与CSS相比&#xff0c;WXSS扩展的特性有&#xff1a; rpx尺寸单位imprt样式导入 rpx尺寸单位 rpx是微信小程序中独有的&#xff0c;用来…

第三节课,后端登录【1】.2--本人

一、视频链接 网址&#xff1a; 后端用户脱敏和session-CSDN直播 二、代码开始 2.1 新建一个request参数。完成用户登录态键 快捷建&#xff0c; 全局变量 代码&#xff1a; // 3.记录用户的登录态/*** 这段代码是Java Web开发中的一部分&#xff0c;用于在会话&#xff08…

面试:finalize

一、概述 将资源释放和清理放在finalize方法中非常不好&#xff0c;非常影响性能&#xff0c;严重时甚至会引起OOM&#xff08;Out Of Memory&#xff09;&#xff0c;从Java9开始就被标注为Deprecated&#xff0c;不建议被使用了。 二、两个重要的队列 1、unfinalized 队列 当…

为什么 Facebook 不使用 Git?

在编程的世界里&#xff0c;Git 就像水一样常见&#xff0c;以至于我们认为它是创建和管理代码更改的唯一可行的工具。 前 Facebook 员工&#xff0c;2024 年 首先&#xff0c;我为什么关心&#xff1f; 我致力于构建 Graphite&#xff0c;它从根本上受到 Facebook 内部工具的…

FSMC读取FPGA的FIFO

一、硬件说明 FSMC配置 单片机的代码如下&#xff1a; #define VALUE_ADDRESS_AD1 (__IO uint16_t *)0x60400000while (1){if(!HAL_GPIO_ReadPin(GPIOF, GPIO_PIN_8)) //数据非空{data *(__IO uint16_t *)VALUE_ADDRESS_AD1;data2 *(__IO uint16_t *)VALUE_ADDRESS_AD1…

网上订餐系统,基于 SpringBoot+Vue+MySQL 开发的前后端分离的网上订餐系统设计实现

目录 一. 前言 二. 功能模块 2.1. 用户功能模块的实现 2.2. 管理员功能模块的实现 三. 部分代码实现 四. 源码下载 一. 前言 随着我国经济的飞速发展&#xff0c;人们的生活速度明显加快&#xff0c;在餐厅吃饭排队的情况到处可见&#xff0c;近年来由于新兴IT行业的空前…

python的turtle库画直线

1.画一条直线 让画笔从(0,0)划到&#xff08;100,100&#xff09;&#xff0c;在turtle中画笔是一只小乌龟。 import turtle turtle.setup(800,800,0,0)#turtle.setup(width,height,startx,starty)来设置窗口初始位置及大小 turtle.goto(100,100)2.画一条折线 left和right使小…

安装crossover游戏提示容量不足怎么办 如何把游戏放到外置硬盘里 Mac电脑清理磁盘空间不足

CrossOver作为一款允许用户在非原生操作系统上运行游戏和应用程序的软件&#xff0c;为不同平台的用户提供了极大的便利。然而&#xff0c;随着游戏文件大小的不断增加&#xff0c;内置硬盘的容量往往无法满足安装需求。幸运的是&#xff0c;通过一些简单的步骤&#xff0c;我们…

怎么样解决web图片加载未更新问题|浏览器图片未更新问题

问题列举 为什么我本地资源改变但是我在用 tomcat 预览网页时图片仍然未之前的图片? 为什么我当前网页的图片是之前的我换浏览器就变了? tomcat启动后&#xff0c;为什么访问项目中的图片无效解决? 解决方案 问题一 为什么我本地资源改变但是我在用 tomcat 预览网页时…

关于使用SpringSecurity框架发起JSON请求,但因登陆失效导致响应403的问题。

这里记录一个生产中遇到的一个问题。 现有环境是基于SpringBoot 2.6.8&#xff0c;然后是前后台一体化的项目。 安全框架使用的是内置版本的SpringSecurity。 在实际使用过程中遇到一个问题。 就是当用户登陆失效后&#xff0c;前端操作JSON请求获取列表数据&#xff0c;但…

编程学习路线

Java最强学习路线 快来官网定制一套属于自己的学习路线吧 官方网址&#xff1a; Learn to become a modern Java developerCommunity driven, articles, resources, guides, interview questions, quizzes for java development. Learn to become a modern Java developer by…

架构师系列- 消息中间件(12)-kafka基础

1、应用场景 1.1 kafka场景 Kafka最初是由LinkedIn公司采用Scala语言开发&#xff0c;基于ZooKeeper&#xff0c;现在已经捐献给了Apache基金会。目前Kafka已经定位为一个分布式流式处理平台&#xff0c;它以 高吞吐、可持久化、可水平扩展、支持流处理等多种特性而被广泛应用…

go 测试和文件

go 测试和文件 需求传统测试单元测试牛刀小试总结练习文件介绍打开关闭文件读文件一次性读取文件写文件文件或文件夹是否存在文件拷贝 需求 有一个函数&#xff0c;怎样确认他运行结果是正确的&#xff1f; func addUpper(n int)int {res : 0for i : 1; i < n; i {res1}r…

牛客NC368 质数的计数【中等 基础数学,数论 C++/Java/Go/PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/190167d1990442da9adb133980259a27 思路 判断x是否是质数&#xff1a;这是判断质数最好的代码了public boolean isPrime(int x){if(x 2 || x3) return true;if(x%6!1 && x%6!5) return false; //不在6倍…

微服务之分布式理论概述

一、分布式技术相关的理论 CAP理论 CAP定理(CAP theorem)&#xff0c;⼜被称作布鲁尔定理(Eric Brewer)&#xff0c;1998年第⼀次提出. 最初提出是指分布式数据存储不可能同时提供以下三种保证中的两种以上: (1) ⼀致性(Consistency): 每次读取收到的信息都是最新的; (2) …

7天入门Android开发之第1天——初识Android

一、Android系统 1.Linux内核层&#xff1a; 这是安卓系统的底层&#xff0c;它提供了基本的系统功能&#xff0c;如内存管理、进程管理、驱动程序模型等。安卓系统构建在Linux内核之上&#xff0c;借助于Linux的稳定性和安全性。 2.系统运行库层&#xff1a; 这一层包括了安卓…

Python用于高级异常检测和聚类的工具库之BanditPAM使用详解

概要 Python BanditPAM库是一个用于高级异常检测和聚类的工具,具有强大的特性和灵活的功能,可以发现数据中的异常点并进行有效的聚类分析。本文将详细介绍Python BanditPAM库的安装、特性、基本功能、高级功能以及总结。 安装 首先,需要安装Python BanditPAM库。 可以使用…

Hadoop之路

hadoop更适合在liunx环境下运行&#xff0c;会节省后期很多麻烦&#xff0c;而用虚拟器就太占主机内存了&#xff0c;因此后面我们将把hadoop安装到wsl后进行学习,后续学习的环境是Ubuntu-16.04 &#xff08;windows上如何安装wsl&#xff09; 千万强调&#xff0c;有的命令一…

Python-VBA函数之旅-list函数

目录 一、list函数的常见应用场景&#xff1a; 二、list函数使用注意事项&#xff1a; 三、如何用好list函数&#xff1f; 1、list函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;https://blog.csdn.net…

2015-2023年上市公司商道融绿ESG评级数据

2015-2023年上市公司商道融绿ESG评级数据 1、时间&#xff1a;2015-2023年 2、来源&#xff1a;整理自WIND 3、指标&#xff1a;代码、名称、商道融绿ESG评级 4、范围&#xff1a;上市公司 5、指标解释&#xff1a; 商道融绿ESG评级体系是一种全新的评级体系&#xff0c;…