【图论】——理论基础总结

图论这一章尤其需要图例进行说明,方便理解,对于作者来说很费时间,本文主要为自己复习方便,所以并不会写的非常详细,见谅。

图论

图的基本概念

基本要素:

  • 节点

两点连成线,多个点连成的线称为图。当然也可以就一个节点,或者啥也没有(空图)。

图的种类

方向的概念
根据边有无方向划分为:

  • 无向图
  • 有向图

权重的概念
边可以有权重,根据有无权重和方向:

  • 加权有向图
  • 加权无向图

度的概念

  • 针对无向图,对于某节点,有几条边连着该节点,就称该节点的度为多少
  • 对于有向图,每个节点有出度和入度
    • 出度:从该节点出发的边的个数
    • 入度:进入该节点的边的个数

连通性的概念

无向图中,根据任意两个节点之间能否到达:

  • 连通图:如果任意两个节点都是可以到达的,可以称之为连通图。
  • 非连通图:反之,如果有任意两个节点不能到达,就是非连通图。

有向图中,注意,是任意两个节点都能互相到达,单向的到达不是强连通图!

  • 强连通图:在有向图中,任何两个节点是可以相互到达的,我们称之为 强连通图。

连通分量的概念
在无向图中,极大连通子图称为该图的一个连通分量。这里最重要的概念是 “ 极大 ” ,只有极大的连通子图才是连通分量!

强连通分量
在有向图中,极大强连通图称为该图的强连通分量。
这里,既是“ 极大 ” , 又是“ 强(任意节点双向可到达) ”,才是强连通分量。

图的构造

基本概念搞清楚了,那么如何用代码表示图?
一般包括:邻接表、邻接矩阵或者类

  1. 邻接矩阵(Adjacency Matrix)
    • 对于一个有 n n n 个顶点的图 G = ( V , E ) G=(V,E) G=(V,E),其邻接矩阵是一个 n × n n×n n×n 的矩阵 A A A。如果图是无向图,当顶点 i i i 和顶点 j j j 之间有边相连时, A i j = A j i = 1 A_{ij}=A_{ji}=1 Aij=Aji=1(若为加权图,则为边的权重值),否则为 0;
    • 如果图是有向图,当存在从顶点 i i i 到顶点 j j j 的边时, A i j = 1 A_{ij}=1 Aij=1(或边的权重), A j i A_{ji} Aji 则根据是否有从 j j j i i i 的边来确定。
    • 这种表示方法的优点是判断两个顶点是否相邻很方便,时间复杂度为 O ( 1 ) O(1) O(1)。缺点是对于稀疏图,会浪费大量的存储空间,因为大量的元素为 0。
    • 例如,一个有 1000 个顶点但只有 100 条边的图,邻接矩阵需要存储 1000 × 1000 = 1000000 1000×1000 = 1000000 1000×1000=1000000 个元素,但实际有用的信息很少。

上面的描述有点抽象

  • 简单说,邻接矩阵就是一个二维矩阵(计算机中叫二维数组)来表示图结构,以节点为主体来描述图
  • 有多少节点就申请多大的二维数组
  • 例如: g r i d [ 2 ] [ 5 ] = 6 grid[2][5] = 6 grid[2][5]=6,表示 节点 2 节点 2 节点2 连接 节点 5 节点5 节点5 为有向图,节点2 指向 节点5,边的权值为 6 6 6
  • 如何用邻接矩阵表示无向图呢? g r i d [ 2 ] [ 5 ] = 6 grid[2][5] = 6 grid[2][5]=6 g r i d [ 5 ] [ 2 ] = 6 grid[5][2] = 6 grid[5][2]=6,表示节点2 与 节点5 相互连通,权值为6。

分析邻接矩阵的优缺点:
缺点:

  • 一个有 N N N 个节点的图,需要申请 N 2 N^2 N2 尺寸的二维数组,需要 N 2 N^2 N2 尺寸的空间,显然邻接矩阵这种表达方式容易造成空间浪费,
  • 并且,在寻找节点连接情况的时候,需要遍历整个矩阵,即时间复杂度也相当高,达到了 O ( l o g N 2 ) O (logN^2) O(logN2)

优点:

  • 表达方式简答,易于理解
  • 检查任意两个顶点之间是否存在边的操作非常快
  • 适合稠密图,在边数接近顶点平方数的图中,邻接矩阵是一种空间效率较高的表示方法
  1. 邻接表(Adjacency List)
    • 对于图中的每个顶点,用一个链表(或其他合适的数据结构,如数组等)来存储与它相邻的顶点。
    • 在有向图中,可以分别存储出边邻接表和入边邻接表。这种表示方法对于稀疏图很节省空间,只存储实际存在的边信息。
    • 其优点是存储效率高,尤其是在边数较少的情况下。
    • 缺点是查询两个顶点是否相邻的时间复杂度比邻接矩阵高,需要遍历链表,平均时间复杂度为 O ( d ) O(d) O(d) d d d 为顶点的度)。
    • 例如,在一个社交网络图中,如果用邻接表表示,每个用户的好友列表就是其邻接表,这样可以高效地存储和查询用户之间的关系。

简单说:

  • 邻接表以边为主体,使用数组+链表来表示边的连接情况,有多少边就申请多少对应大小的链表
  • 优点:
    • 对于稀疏图的存储,只需要存储边,空间利用率高
    • 遍历节点连接情况,相对容易
  • 缺点:
    • 检查任意两个节点之间是否存在边,效率相对较低,需要 O ( V ) O(V) O(V)时间,V表示某节点连接其他节点的数量
    • 实现相对复杂,不直观,不易理解

图的遍历方式

  • 深度优先搜索(DFS)
  • 广度优先搜索(BFS)

注意!

  • 二叉树的递归遍历,是dfs在二叉树上的遍历方式
  • 二叉树的层序遍历,是bfs在二叉树上的遍历方式
  1. 深度优先搜索(DFS - Depth - First - Search)

    • 从图中的某个起始顶点 v v v 开始,首先访问顶点 v v v
    • 然后选择一个与 v v v 相邻且未被访问过的顶点 w w w,递归地对 w w w 进行深度优先搜索,直到遇到一个顶点,其所有相邻顶点都已被访问过,然后回溯到上一个有未访问邻接顶点的顶点,继续搜索。
    • 这个过程可以使用栈(递归调用本身就利用了系统栈)来实现。
    • 例如,在一个迷宫图中,可以想象为沿着一条通道一直走,直到走不通了,再返回上一个岔路口选择另一条路。
    • 在实现中,可以使用一个布尔数组来标记顶点是否已被访问。深度优先搜索可以用来判断图是否连通、寻找图的连通分量、生成图的生成树等。
  2. 广度优先搜索(BFS - Breadth - First - Search)

    • 从起始顶点 v v v 开始,首先访问顶点 v v v,然后依次访问 v v v 的所有未被访问过的邻接顶点,接着再依次访问这些邻接顶点的未被访问过的邻接顶点,以此类推,按照层次进行遍历。这个过程可以使用队列来实现。例如,在一个网络拓扑图中,如果从一个节点开始传播信息,BFS 可以模拟信息按照距离逐步传播的过程。
    • 广度优先搜索可以用于计算图中顶点的最短路径(在无权图中,距离就是边的数目)、判断图的连通性等。在实现时,同样需要一个布尔数组来标记顶点是否已被访问,还需要一个队列来存储待访问的顶点。

最短路径算法

  1. 迪杰斯特拉算法(Dijkstra’s Algorithm)

    • 用于计算加权有向图(或加权无向图)中一个顶点到其他所有顶点的最短路径。算法维护一个集合 S S S,表示已经找到最短路径的顶点集合,初始时只包含起始顶点。对于每个顶点 v v v,记录从起始顶点到 v v v 的当前最短距离 d [ v ] d[v] d[v]。在每次迭代中,选择不在 S S S 中且 d [ v ] d[v] d[v] 最小的顶点 u u u,将其加入 S S S,然后更新与 u u u 相邻的顶点的最短距离估计。例如,在一个交通网络中,要找到从一个城市到其他所有城市的最短距离,迪杰斯特拉算法可以通过逐步扩展已确定最短路径的城市集合来计算。
    • 算法的时间复杂度一般为 O ( ∣ V ∣ 2 ) O(|V|^2) O(V2) ∣ V ∣ |V| V 是顶点数),使用合适的数据结构(如优先队列)可以优化到 O ( ∣ E ∣ + ∣ V ∣ l o g ∣ V ∣ ) O(|E| + |V|log|V|) O(E+VlogV) ∣ E ∣ |E| E 是边数)。
  2. 贝尔曼 - 福特算法(Bellman - Ford Algorithm)

    • 可以处理有负权重边的图(但不能有负权重环),用于计算单源最短路径。算法通过对所有边进行多次松弛操作来逐步逼近最短路径。每次迭代,遍历图中的所有边,尝试更新通过该边连接的两个顶点的最短距离。例如,在一些经济模型中,可能会出现负权重的情况,贝尔曼 - 福特算法可以用于分析成本等相关问题。
    • 算法的时间复杂度为 O ( ∣ V ∣ ∣ E ∣ ) O(|V||E|) O(V∣∣E)
  3. 弗洛伊德算法(Floyd - Warshall Algorithm)

    • 用于计算加权图(有向或无向)中所有顶点对之间的最短路径。算法使用动态规划的思想,通过一个二维数组来存储顶点之间的最短距离,逐步更新数组的值。例如,在分析一个大型通信网络中任意两个节点之间的最短通信路径时,弗洛伊德算法可以一次性计算出所有的最短路径信息。
    • 算法的时间复杂度为 O ( ∣ V ∣ 3 ) O(|V|^3) O(V3)

生成树

  1. 生成树的定义

    • 对于一个连通图 G = ( V , E ) G=(V,E) G=(V,E),生成树是 G G G 的一个子图 T = ( V , E ′ ) T=(V,E') T=(V,E),其中 E ′ ⊆ E E'\subseteq E EE,且 T T T 是一棵树(即无环且连通),包含图 G G G 的所有顶点。例如,在一个电网图中,生成树可以表示一种最小的电线连接方式,使得所有节点都能有电且没有多余的回路。
  2. 最小生成树(MST - Minimum Spanning Tree)

    • 在加权连通图中,所有生成树中边的权重之和最小的生成树称为最小生成树。常见的计算最小生成树的算法有:
    • 普里姆算法(Prim’s Algorithm):从任意一个顶点开始,每次选择一个与当前生成树相连且边权重最小的顶点,将其加入生成树,直到所有顶点都被包含。算法时间复杂度一般为 O ( ∣ V ∣ 2 ) O(|V|^2) O(V2),使用合适的数据结构可以优化到 O ( ∣ E ∣ + ∣ V ∣ l o g ∣ V ∣ ) O(|E| + |V|log|V|) O(E+VlogV)
    • 克鲁斯卡尔算法(Kruskal’s Algorithm):将图中的所有边按照权重从小到大排序,然后依次选择边,如果选择的边不会形成环,则将其加入生成树,直到生成树包含 n − 1 n - 1 n1 条边( n n n 是顶点数)。算法时间复杂度主要取决于边的排序,一般为 O ( ∣ E ∣ l o g ∣ E ∣ ) O(|E|log|E|) O(ElogE)。最小生成树在网络设计、电路布线等领域有广泛应用。

拓扑排序

  1. 拓扑排序的定义

    • 对于一个有向无环图(DAG - Directed Acyclic Graph),拓扑排序是将图中所有顶点排成一个线性序列,使得对于图中的任意一条有向边 ( u , v ) (u,v) (u,v),顶点 u u u 在序列中都排在顶点 v v v 的前面。例如,在一个课程学习的先后顺序图中,拓扑排序可以表示课程的学习顺序,先修课程排在前面,后修课程排在后面。
  2. 拓扑排序算法

    • 一种常见的方法是使用深度优先搜索。在 DFS 遍历过程中,当一个顶点的所有后继顶点都被访问完后,将该顶点加入拓扑排序序列。也可以使用入度表的方法,不断删除入度为 0 的顶点,并更新其邻接顶点的入度,直到所有顶点都被处理。拓扑排序在任务调度、项目规划等领域有重要应用,用于确定任务的执行顺序。

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

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

相关文章

unity 中使用zeroMq和Mqtt 进行通讯

最近我在做一个车上的HMI项目,也就是车机应用,需要与云端和域控进行通信。HMI的功能已经外包了,但消息的统一层留给我自己来做。因为项目组其他人都没有经验,所以这个任务就落到了我头上,尽管我自己也没有太多经验&…

Java | Leetcode Java题解之第526题优美的排列

题目&#xff1a; 题解&#xff1a; class Solution {public int countArrangement(int n) {int[] f new int[1 << n];f[0] 1;for (int mask 1; mask < (1 << n); mask) {int num Integer.bitCount(mask);for (int i 0; i < n; i) {if ((mask & (1…

命令行参数、环境变量、地址空间

命令行参数&#xff1a; int main(int argc, char *argv[ ])&#xff0c;main的参数可带可不带。argc参数通常代表后面的char *argv的元素个数有多少。 在linux中会把输入的字符串存到char *argv[ ]中&#xff0c;在数组的结尾为NULL。 命令行参数可以让同一个程序可以通过不同…

软件测试学习笔记丨SeleniumPO模式

本文转自测试人社区&#xff0c;原文链接&#xff1a;https://ceshiren.com/t/topic/22525 本文为霍格沃兹测试开发学社的学习经历分享&#xff0c;写出来分享给大家&#xff0c;希望有志同道合的小伙伴可以一起交流技术&#xff0c;一起进步~ 说明&#xff1a;本篇博客基于sel…

网络自动化03:简单解释send_config_set方法并举例

目录 拓扑图设备信息 netmiko涉及方法send_config_set()方法的简单示例代码输出结果代码解释导入模块配置信息config_device_interface_description 函数主程序块总结 send_config_set方法参数&#xff1a;1. enter_config_mode2. config_commands3. enter_config_mode4. error…

UI自动化测试 —— CSS元素定位实践!

前言 自动化测试元素定位是指在自动化测试过程中&#xff0c;通过特定的方法或策略来准确识别和定位页面上的元素&#xff0c;以便对这些元素进行进一步的操作或断言。这些元素可以是文本框、按钮、链接、图片等HTML页面上的任何可见或不可见的组件。 在自动化测试中&#xf…

zxing生成、解析二维码,条形码

1、maven依赖 <!--zxing依赖--><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.1.0</version></dependency><dependency><groupId>com.google.zxing</groupI…

有效增加网站流量的实用策略和技巧

内容概要 在数字化时代&#xff0c;网站流量的增加被视为在线业务成功的关键。网站流量不仅仅意味着访问者的数量&#xff0c;还影响着品牌知名度、用户参与度和销售转化率。针对这一需求&#xff0c;企业需要采取行之有效的策略&#xff0c;例如搜索引擎优化&#xff08;SEO&…

玄机-应急响应- Linux入侵排查

一、web目录存在木马&#xff0c;请找到木马的密码提交 到web目录进行搜索 find ./ type f -name "*.php" | xargs grep "eval(" 发现有三个可疑文件 1.php看到密码 1 flag{1} 二、服务器疑似存在不死马&#xff0c;请找到不死马的密码提交 被md5加密的…

从 vue 源码看问题 — vue 如何进行异步更新?

前言 在上一篇 如何理解 vue 响应式&#xff1f; 中&#xff0c;了解到响应式其实是通过 Observer 类中调用 defineReactive() 即 Object.defineProperty() 方法为每个目标对象的 key&#xff08;key 对应的 value 为非数组的&#xff09; 设置 getter 和 setter 实现拦截&…

本地部署bert-base-chinese模型交互式问答,gradio

首先下载bert-base-chinese&#xff0c;可以在 Huggingface, modelscope, github下载 pip install gradio torch transformers import gradio as gr import torch from transformers import BertTokenizer, BertForQuestionAnswering# 加载bert-base-chinese模型和分词器 mod…

SYN590RH是SYNOXO全新开发设计的一款宽电压范围,低功耗,高性能,无需外置AGC电容de单芯片ASK或00 K射频接收器

一般描述 SYN590RH是SYNOXO全新开发设计的一款宽电压范围&#xff0c;低功耗&#xff0c;高性能&#xff0c;无需外置AGC电容&#xff0c;灵敏度达到典型-110 dBm,400MHz~450MHz频率范围应用的单芯片ASK或00 K射频接收器。 SYN590RH是一款典型的即插即用型单片高…

Unreal5从入门到精通之如何在指定的显示器上运行UE程序

前言 我们有一个设备,是一个带双显示器的机柜,主显示器是一个小竖屏,可以触屏操作,大显示器是一个普通的横屏显示器。我们用这个机柜的原因就是可以摆脱鼠标和键盘,直接使用触屏操作,又可以在大屏观看,非常适合用于教学。 然后我们为这款机柜做了很多个VR项目,包括Uni…

C++中unordered_map和unordered_set的介绍以及用哈希表封装实现unordered_map和unordered_set

目录 1.unordered_map和unordered_set的使用 1.1unordered_set类的介绍 1.2unordered_set和set的使用差异 1.3unordered_map和map的使用差异 1.4unordered_multimap/unordered_multiset 2.用哈希表封装实现unordered_set和unordered_map 2.1实现出复用哈希表的框架并支持…

stm32学习4

学习目录 一.流水灯1.创建文件2.编写相关代码 一.流水灯 1.创建文件 将方法进行分类保存在不同的 .c 文件中&#xff0c;方便复用和寻找&#xff1b; 创建Hardware\LED文件&#xff0c;其中有led.c和led.h文件&#xff0c;用于存放有关LED灯操作的方法&#xff1b; 在User文…

JVM结构图

JVM&#xff08;Java虚拟机&#xff09;是Java编程语言的核心组件之一&#xff0c;负责将Java字节码翻译成机器码并执行。JVM由多个子系统组成&#xff0c;包括类加载子系统、运行时数据区、执行引擎、Java本地接口和本地方法库。 类加载子系统&#xff08;Class Loading Subsy…

mysql之命令行基础指令

一&#xff1a;安装好mysql后&#xff0c;注册好账号密码。 二&#xff1a;在命令行进行登录的指令如下 mysql -u用户名 -p 例如&#xff1a;mysql -uroot -p; 然后按下回车&#xff0c;进入输入密码。 三&#xff1a;基本指令&#xff1a; 1&#xff1a;查看当前账户的所有…

LabVIEW适合开发的软件

LabVIEW作为一种图形化编程环境&#xff0c;主要用于测试、测量和控制系统的开发。以下是LabVIEW在不同应用场景中的适用性和优势。 一、测试与测量系统 LabVIEW在测试与测量系统中的应用广泛&#xff0c;是工程测试领域的主流工具之一。利用其强大的数据采集与处理功能&…

MySQL表的增删改查(CRUD3约束)

这次我们开始先不复习嗷&#xff0c;等到把数据表的删除说完咱们统一&#xff0c;总结书写 1.数据表的删除&#xff1a; 语法&#xff1a; 1. 使用 DROP TABLE 语句删除单个表 基本语法&#xff1a;DROP TABLE [IF EXISTS] table_name; table_name是要删除的表的名称。IF EXIS…