并查集与图

并查集与图

  • 一、并查集
    • 概念
    • 实现原理
    • 代码实现
      • 查找根节点
      • 合并两颗树
      • 判断是否是同一棵树
      • 树的数量
  • 二、图的基本概念
    • 定义
    • 分类
    • 完全图
    • 顶点的度
    • 连通图
  • 三、图的存储结构
    • 分类
    • 邻接表
      • 邻接表的结构
      • 代码实现
    • 邻接矩阵
      • 代码实现
  • 四、图的遍历
    • 方式
    • 广度优先
    • 深度优先
  • 五、最小生成树
    • 概念
    • Kruskal算法
      • 原理
      • 代码实现
    • Prim算法
      • 原理
      • 代码实现
  • 六、单源最短路径
    • 概念
    • Dijkstra
      • 原理
      • 代码实现
      • 缺陷
    • BellmanFord
      • 原理
      • 代码实现
  • 七、多源最短路径
    • 概念
    • 原理
    • 代码实现

一、并查集

概念

并查集是由多棵树组成的,本质上一个森林,常用于解决图的判环问题,两个集合是否有交集等等。

实现原理

并查集采用双亲表示法,和堆类似,都采用数组来实现,如下图,以10个元素为例,初始时,值都是-1,表示10棵树,元素值的绝对值表示树中的节点个数
在这里插入图片描述
如下图,将下标为9的元素合并到下标为5的树上,将下标为5的值加上下标为9的值,然后将下标为9的值改为5,便于找到它的双亲
在这里插入图片描述

代码实现

查找根节点

要合并两个树,就得先分别找到这两颗树的根节点,然后才能进行合并,如下图
在这里插入图片描述

合并两颗树

首先先找到两颗树的根节点,根据根节点是否相同,来判断是不是已经是同一颗树了,如果是就返回,不是再进行合并,同时,将节点少的树往节点多的树上合并
在这里插入图片描述

判断是否是同一棵树

只要判断是不是同一个根节点即可
在这里插入图片描述

树的数量

只要元素的值为-1的,就表示它是一棵树,统计计数即可
在这里插入图片描述

二、图的基本概念

定义

图是由顶点和边组成的一种数据结构,用G = (V, E)表示,G表示图(graph),V(vertex)表示顶点,E(edge)表示边

分类

图分为有向图和无向图两种,有向图常用于表示单向关系,比如B站关注了某个up主,就是单向的,而无向图常用于表示像微信、QQ这样双向的好友关系

有向图,如下图
在这里插入图片描述

无向图,如下图
在这里插入图片描述

完全图

完全图是一种任意两个顶点都直接相连的图,无向图中的完全图有n*(n-1)/2条边,有向图中的完全图有n*(n-1)条边,即任意两个顶点都有两条边

顶点的度

无向图中,顶点的度=出度=入度,因为无向图的边没有方向,所以都相等,而在有向图中,顶点的度=出度+入度

连通图

图和树不同,图不一定是连通的,可能存在孤岛,即没有前往某个节点的路径,它与其它节点是脱离开的,如下图,红色顶点就是一个孤岛
在这里插入图片描述

三、图的存储结构

分类

图的存储结构分为两种,一种是邻接矩阵

邻接表

邻接表的结构

邻接表采用类似于哈希表的方式,先用一个数组,数组的每个元素都代表一个顶点,顶点下面都挂着的一个链表,链表的每个节点都是一条边,对于有向图,这里这考虑出边,不考虑入边,如果要考虑入边,就得再加一个邻接表
在这里插入图片描述

代码实现

首先,定义出边的结构,用模板类型W,来表示权值类型,因为是挂在对应的顶点下面,所以可以不存储顶点的下标
在这里插入图片描述
顶点的类型可能有很多中,所以采用模板类型V,W是权值的类型,Direction是非类型模板参数,false表示无向图,true表示有向图
在这里插入图片描述
确定图的成员,分别有顶点集合,邻接表,以及一个顶点与其下标映射的Map,便于后面插入的时候,找到顶点的下标
在这里插入图片描述
构造函数用来开辟邻接表的空间,以及初始化成员
在这里插入图片描述
定义一个查找顶点下标的接口
在这里插入图片描述
添加边,采用链表的头插,如果是无向图,则需要插入两条边,因为i->j,那也一定可以j->i,所以需要插入两条边
在这里插入图片描述

邻接矩阵

代码实现

MAX_W这个参数用来初始化二维数组,毕竟一开始的邻接矩阵的每个顶点都是一个孤岛
在这里插入图片描述
成员和邻接表类似,只是将邻接表改为了二维数组,二维数组的每个元素的值,都是边的权值
在这里插入图片描述
构造函数,用来开辟空间,初始化成员
在这里插入图片描述
添加边,这里采用两个函数,是因为后面有些地方会直接使用上面的函数,不需要通过函数获取顶点下标
在这里插入图片描述
注意:下面的所有算法,都是在邻接矩阵中实现的

四、图的遍历

方式

如图、树这种数据结构,一般都采用深度优先或广度优先的方式来进行遍历,值得注意的是,这里遍历的是顶点,不是边!!!

广度优先

广度优先遍历方式,需要借助队列来实现,队列用来存顶点的下标,srci是起始顶点的下标,visited是一个标记数组,当某个顶点下标入队列后,就将其标记为true,表示访问过了,来防止后续可能会重复入队列,第一个for循环是用来便于一层一层打印的,类似于打印树的每一层
在这里插入图片描述
值得注意的是,图不一定是连通的,可能存在孤岛,遍历不到,所以需要循环遍历标记数组,以此来遍历所有顶点
在这里插入图片描述

深度优先

深度优先遍历,采用递归的方式实现,同样需要借助标记数组,来标记访问过的节点
在这里插入图片描述
同广度优先,需要解决可能出现的孤岛问题
在这里插入图片描述

五、最小生成树

概念

最小生成树是一种特殊的连通图,它只有n-1条边,刚刚好可以使图连通,n是顶点个数,最小生成树也是不能成环的,否则也无法使图连通,同时,这n-1条边的权值和是最小的。

注意:最小生成树也可能不唯一!!!

Kruskal算法

原理

Kruskal算法是一种找全局最优解的贪心,它每次都找最权值最小的边,当然,在会构成环的时候,会抛弃构成环的那条边,找另外的边

代码实现

首先,先初始化一下最小生成树
在这里插入图片描述
在这里插入图片描述
这是要使用的边结构,重载>,是为了后面建立小堆
在这里插入图片描述

这里借助优先级队列,来便于每次找最小的边
在这里插入图片描述
选边,需要借助前面讲过的并查集,来判断是不是会成环,成环则抛弃这条边,找另外的边,不成环,将边的起始点和终止点的下标加入并查集,来合并顶点
在这里插入图片描述
最后,再判断一下,是否是n-1条边,是就将权值和返回
在这里插入图片描述

Prim算法

原理

Prim算法是一种找局部最优解的贪心,它采用了两个集合,集合中的元素是顶点的下标,姑且称为源集合和目标集合,分别用X和Y表示。开始时,X只有一个顶点a的下标,Y有其它顶点的下标,然后找顶点a到Y集合中元素对应的顶点的最小权值,具体步骤如下图

核心思路:每次找X中的某个顶点到Y中的某个顶点直接相连的且是最小权值的边
在这里插入图片描述

代码实现

初始准备工作
在这里插入图片描述
定义X与Y集合,开始时,X集合只有一个元素,Y集合有n-1个元素
在这里插入图片描述
先把a顶点直接相连的边全部插入到优先级队列中,此后,优先级队列中都是X集合中的顶点连接的边
在这里插入图片描述
选出优先级队列中的最小边,判断边的目标顶点是不是已经在X集合中了,在就表示成环了,因为一个顶点不可能被两次加入一个集合

添加边后,再将边的目标点连接的边都加入到优先级队列中,不过需要判断一下目标点连接的边的另一顶点是否已经在X集合中了
在这里插入图片描述
最后,判断一下是否是n-1条边
在这里插入图片描述

六、单源最短路径

概念

单源最短路径,指的是从某个点到其它点的路径,假设有顶点a、b、c、d、e,以a为源点,从a到b所有路径中,权值和最小的那条路径就是最短路径,而a到c、d、e,也是同理,所以被称为单源最短路径

Dijkstra

原理

这里采用两个一维数组,长度为顶点的个数,一个数组中的每个元素表示源点到该元素顶点的路径的权值的最小值,另一个数组中的每个元素存储的是它的双亲,具体情况,如下图,*表示最大值,以S为源点,先根据S的所有出边,更新对应的最短路径,s到y和t的最短路径被更新,然后以y为起点,找它的出边,更新s到t、x、z的最短路径,因为s到z的路径最短,下次再以z为起点,找它的出边等等,每一步都是贪心

在这里插入图片描述

代码实现

先进行初始化操作,数组S用来标记已经找到最短路径的顶点
在这里插入图片描述
因为有n个顶点,所以最外层循环n次,第一个内循环,则是找出路径权值最小的起点,第二个内循环则负责更新出最短路径,同时要保证目标顶点没有被确定最短路径
在这里插入图片描述

缺陷

Dijkstra算法的效率很高,但是也存在缺陷,就是无法解决带有负权路径的情况,因为此时使用贪心就不准确了,不能每次确定最短路径顶点

BellmanFord

原理

BellmanFord算法采用了暴力思想,通过把一条路径都遍历一遍,来确定源点到其它点的最短路径,虽然效率不如Dijkstra算法,但可以很好地解决负权路径问题

代码实现

初始化工作
在这里插入图片描述
内部的两层循环,把每一条路径都遍历一遍,来找到源点到其它点的最短路径,但可能一轮循环无法更新所有源点到其它顶点的最短路径,所以还需要在最外面套一层循环,循环n-1次,来更新出源点到其它点的所有最短路径,至于为什么是n-1,是因为在一条路径上,你只需要n-1条边来连接n个节点,再多的边就构成了一个环路,这里定义了一个变量,当没有更新的时候,也就说明所有源点到其它顶点的最短路径都已经被找到了
在这里插入图片描述
循环完后,还需要判断一下是否存在负权回路,毕竟存在负权回路时,是不可能有最短的路径的
在这里插入图片描述

七、多源最短路径

概念

多源最短路径,则是求的任意两个顶点的最短路径

原理

采用的是FloydWarshall算法,核心思想是动态规划,来寻找最优解,比如找i->j的最短路径,则可以找i->k,k->j的和的最短路径,k为i->j路径上的一个中间点,也有可能k就是i

代码实现

初始化操作,这里采用两个矩阵的形式,同上面的两个算法,只不过变为了二维,同时将直接相连的边在矩阵中进行初始化
在这里插入图片描述
result[i][j],表示从i对应的顶点到j对应的顶点的最短路径值,pPath[i][j],表示i对应顶点到j对应顶点的最短路径中,j对应顶点的父顶点
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图中点的层次——树与图的广度优先遍历

问题描述 代码实现 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 1e5 10;int n, m; int h[N], ne[N * 2], e[N * 2], idx; int d[N]; // 从节点1到当前节点的距离 int q[N * 2]; // 数组模拟队列void ad…

BabylonJS 6.0文档 Deep Dive 摄像机(五):多视角(二)

1. 摄像机激活 一般来说&#xff0c;一个场景&#xff08;Scece&#xff09;只有一个激活相机&#xff0c;可以使用的activeCamera属性来指定它。但您也可以使用以下代码定义多个active相机来达成多视角的效果&#xff1a; scene.activeCameras.push(camera); scene.activeCa…

TensorRT英伟达官方示例解析(三)

系列文章目录 TensorRT英伟达官方示例解析&#xff08;一&#xff09; TensorRT英伟达官方示例解析&#xff08;二&#xff09; TensorRT英伟达官方示例解析&#xff08;三&#xff09; 文章目录 系列文章目录前言一、04-BuildEngineByONNXParser----pyTorch-ONNX-TensorRT生成…

探索设计模式的魅力:深入理解面向对象设计的深层原则与思维

如何同时提高一个软件系统的可维护性 和 可复用性是面向对象对象要解决的核心问题。 通过学习和应用设计模式&#xff0c;可以更加深入地理解面向对象的设计理念&#xff0c;从而帮助设计师改善自己的系统设计。但是&#xff0c;设计模式并不能够提供具有普遍性的设计指导原则。…

SAP ERP 物料主数据同步外围系统

物料主数据集成在很多项目是比较常见的需求&#xff0c;在做系统实现之前我们需要明确涉及的业务流程和需求范围&#xff0c;并且对每个系统的业务边界进行明确&#xff1a; 如果是从SAP ERP 向其他系统推送数据&#xff0c;并且实时性要求高的情况下&#xff0c;我一般倾向于在…

开关电源空载电流测试方法大全

空载电流测试原理 开关电源空载电流是指电源在没有负载的情况下所消耗的电流。空载电流的大小会影响到电源的工作效率和稳定性&#xff0c;因此测量开关电源的空载电流是非常必要的。 开关电源空载电流测试是在不接任何负载的条件下&#xff0c;用万用表、电流表或者其它专用测…

[MRCTF2020]Ez_bypass1

代码审计&#xff0c;要求gg和id的MD5值相等而gg和id的值不等或类型不等 相同MD5值的不同字符串_md5相同的不同字符串-CSDN博客 不过这道题好像只能用数组 下一步是passwd不能是纯数字&#xff0c;但是下一个判断又要passwd等于1234567 这里通过passwd1234567a实现绕过 原…

【操作系统】实验六 分析源代码

&#x1f57a;作者&#xff1a; 主页 我的专栏C语言从0到1探秘C数据结构从0到1探秘Linux &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f3c7;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64c;收藏❤️关注对我真的很重要&…

【grafana】使用教程

【grafana】使用教程 一、简介二、下载及安装及配置三、基本概念3.1 数据源&#xff08;Data Source&#xff09;3.2 仪表盘&#xff08;Dashboard&#xff09;3.3 Panel&#xff08;面板&#xff09;3.4 ROW&#xff08;行&#xff09;3.5 共享及自定义 四、常用可视化示例4.1…

【mongoDB】图形化界面工具(mongoDB Compass)

官网地址&#xff1a;https://www.mongodb.com/try/download/compass 下载完之后直接安装 桌面上会产生一个快捷方式 双击就会进入mongoDB图形化界面工具

IP组播地址

目录 1.硬件组播 2.因特网范围内的组播 IP组播地址让源设备能够将分组发送给一组设备。属于多播组的设备将被分配一个组播组IP地址 组播地址范围为224.0.0.0~239.255.255.255(D类地址)&#xff0c;一个D类地址表示一个组播组。只能用作分组的目标地址。源地址总是为单播地址…

Vue+OpenLayers7入门到实战:鹰眼控件简单介绍,并使用OpenLayers7在地图上添加鹰眼控件

返回《Vue+OpenLayers7》专栏目录:Vue+OpenLayers7 前言 本章介绍OpenLayers7添加鹰眼控件到地图上的功能。 在OpenLayers中,想要实现鹰眼控件,必须要新建一个数据源,且不能跟其他图层混用,相当于鹰眼是一个单独图层。 补充知识,鹰眼控件是什么? 鹰眼控件是一种在地…

AI教我学编程之SQL Server常见指令以及数据类型

前言 今天在工作的过程中&#xff0c;遇到了许多常见的属性&#xff0c;在此做下记录&#xff0c;方便以后查询 目录 SQL Server 常见指令 对话AI 光有概念怎么行 阶段总结 SQL Server关键字 边学边练 数据类型 看图说话 对话AI 数据类型我知道 括号里的神秘数字 疑问 边练…

彩色图像处理之彩色图像分割的python实现——数字图像处理

原理 彩色图像分割是图像处理领域的一个重要技术&#xff0c;它旨在将一幅彩色图像划分为多个区域或对象。其基本原理包括以下几个方面&#xff1a; 像素特征的提取&#xff1a;彩色图像分割首先涉及到像素级的特征提取。在彩色图像中&#xff0c;常用的特征包括颜色、纹理和…

用大模型训练实体机器人,谷歌推出机器人代理模型

谷歌DeepMind的研究人员推出了一款&#xff0c;通过视觉语言模型进行场景理解&#xff0c;并使用大语言模型来发出指令控制实体机器人的模型——AutoRT AutoRT可有效地推理自主权和安全性&#xff0c;并扩大实体机器人学习的数据收集规模。在实验中&#xff0c;AutoRT指导超过…

HTML-表格

表格 1.基本结构 一个完整的表格由&#xff1a;表格标题、表格头部、表格主体、表格脚注&#xff0c;四部分组成 表格涉及到的标签&#xff1a; table&#xff1a;表格 caption&#xff1a;标题 thead&#xff1a;表格头部 tbody&#xff1a;表格主体 tfoot&#xff1a;表格注…

redis持久化之RDBAOF压缩

前引 1、redis持久化的文件是什么 dump.rdb appendonly.aof 2、这两中文件有什么异同 save 秒 1 alaways everysec no 3、文件存放的位置 dir ./ 4、默认的存放位置:命令启动的地方 dir 自定义的路径 rdb 和aof 文件 存放在同一个路径下面 5、rdb文件默认备份的策略是什么&…

每日一题——LeetCode1331.数组序号转换

方法一 排序哈希Map 首先用一个数组保存排序完的原数组&#xff0c;然后用一个哈希表保存各元素的序号&#xff0c;最后将原属组的元素替换为序号后返回。 var arrayRankTransform function(arr) {let set new Set(arr)let sortArrArray.from(set).sort((a,b)>a-b)let ma…

自学C语言-6

第6章 选择结构程序设计 顺序结构程序设计最简单&#xff0c;但通常无法解决生活中的选择性问题。选择结构程序设计需要用到一些条件判断语句&#xff0c;可实现的程序功能更加复杂&#xff0c;程序的逻辑性与灵活性也更加强大。 本章致力于使读者掌握使用if语句进行条件判断的…

【docker】解决docker overlay2目录占用大量磁盘空间,导致验证码出不来,报错Can‘t create output stream!

问题&#xff1a; 验证码出现Cant create output stream!报错信息 排查&#xff1a; 所在服务器磁盘使用率已经到达100%&#xff0c;经排查&#xff0c;服务器目录/var/lib/docker/overlay2占用大量磁盘空间&#xff0c; 解决&#xff1a; 使用【docker system prune】命令删…