算法通关村第二十关-白银挑战图的存储与遍历

大家好我是苏麟, 今天继续聊图 .

与前面的链表、树等相比,图的存储和遍历要复杂非常多 .所以理解就好 , 面试基本不会让写代码的 . 

图的类型多、表示方式多,相关算法也很多,实现又过于复杂,多语言实现难度太大了。这些算法一般理解就好,不需要面试的时候手写 .

图的实现方式

图的表示方式比前面学习的几种结构都复杂,常见的有两种  : 二维数组表示(邻接矩阵),链表表示(邻接表)。

邻接矩阵是表示图形中顶点之间相邻关系的矩阵,对于 n 个顶点的图而言,矩阵是的 row 和 col 表示的是 1....n个点,矩阵中的1表示有连线,0表示没有连线。

在上图的邻接矩阵需要为每个顶点都分配n个边的空间,其实有很多边都是不存在,因此存储效率比较低。如果图比较稀疏的话,会造成大量的空间浪费,比如在地铁图中,一个站点多的也就与几个站相连少的只有一个,而使用邻接矩阵则需要为每个站点都分配N个空间。

邻接表的实现只关心存在的边,不关心不存在的边,因此没有空间浪费,邻接表由数组+链表组成。

图的遍历

与树一样,图有深度优先和层次遍历两种方式,但是图没有根,因此更多时候将层次遍历称为广度优先遍历BFS。

图的深度优先搜索

深度优先搜索(Depth First Search) 简称深搜或者 DFS,是遍历图存储结构的一种算法,既适用于无向图 (网),也适用于有向图 (网)。

所谓图的遍历,简单理解就是逐个访问图中的顶点,确保每个顶点都只访问一次.

首先通过一个样例,给大家讲解深度优先搜索算法是如何实现图的遍历的 .

图 1无向图的整个过程是 :

1.初始状态下,无向图中的所有顶点都是没有被访问过的,因此可以任选一个顶点出发,遍历整个无向图。

假设从 V1 顶点开始,先访问 V1 顶点,如下图所示 :


2. 紧邻 V1 的顶点有两个,分别是 V2 和 V3,它们都没有被访问过,从它们中任选一个,比如访问 V2 ,. 如下图所示  :

3. 紧邻 V2 的顶点有三个,分别是 V1、V4和 V5,尚未被访问的有 V4 和 V5,从它们中任选一个,比如访问 V4,如下图所示:

4 . 紧邻 V4 的顶点有两个,分别是 V2 和 V8,只有 V8 尚未被访问,因此访问 V8,如下图所示 : 

5 . 紧邻 V8 的顶点有两个,分别是 V4 和 V5,只有 V5 尚未被访问,因此访问 V5,如下图所示:

6 . 和 V5 相邻的顶点有两个,分别是 V2 和 V8,它们都已经访问过了。也就是说,此时从 V5 出发,找不到任何未被访问的顶点了。

这种情况下,深度优先搜索算法会回退到之前的顶点,查看先前有没有漏掉的、尚未访问的顶点:

  • 从 V5 回退到 V8,找不到尚未访问的顶点
  • 从 V8 回退到 V4,还是找不到尚未访问的顶点
  • 从 V4 回退到 V2,也还是找不到尚未访问的顶点
  • 从 V2 回退到 V1,发现 V3 还没有被访问。于是,下一个要访问的顶点就是 V3,如下图所示: 


7 . 紧 V3 的顶点有三个,分别是 V1、V6 和 V7,尚未访问的有 V6 和 V7,因此从它们中任选一个,比如访问 V6,如下图所示:

8 .  紧邻 V6 的顶点有两个,分别是 V3 和 V7,只有 V7 还没有访问,因此访问 V7,如下图所示:


9 . 紧邻 V7 顶点有 V6 和 V3,但它们都已经访问过了,此时面临的情况和第 6 步完全一样,深度优先搜索算法的解决方法也是一样的:

  • 从 V7 回退到 V6,依然找不到尚未访问的顶点
  • 从 V6 回退到 V3,依然找不到尚未访问的顶点
  • 从 V3 回退到 V1,依然找不到尚未访问的顶点

V1 是遍历图的起始顶点,回退到 V1 找不到尚未访问的顶点,意味着以 V1 顶点为突破口,能访问的顶点全部已经访问完了。这种情况下,深度优先搜索算法会从图的所有顶点中重新选择一个尚未访问的顶点,从该顶点出发查找尚未访问的其它顶点。

从图 9 可以看到,图中已经没有尚未访问的顶点了,此时深度优先搜索算法才执行结束

对于连通图来说,深度优先搜索算法从一个顶点出发就能访问图中所有的顶点。但是对于非连通图来说,深度优先搜索算法必须从各个连通分量中选择一个顶点出发,才能访问到所有的顶点。

所谓深度优先搜索,就是从图中的某个顶点出发,不停的寻找相邻的、尚未访问的顶点:

  • 如果找到多个,则任选一个顶点,然后继续从该顶点出发
  • 如果一个都没有找到,则回退到之前访问过的顶点,看看是否有漏掉的,假设从顶点 V 出发,则最终还会回退到顶点 V。此时,深度优先搜索算法会从所有顶点中重新找一个尚未访问的顶点,如果能找到,则以同样的方式继续寻找其它未访问的顶点;如果找不到,则算法执行结束。

通常情况下,深度优先搜索算法访问图中顶点的顺序是不唯一的,即顶点的访问序列可能有多种   ( >= 1)。

图的存储结构有很多种,大体上可以分为顺序存储和链式存储 (又细分为邻接表结构、十字链表结构和邻接多重表结构),各个存储结构有自己的特点。选用不同的存储结构,深度优先搜索算法的具体实现不同,但算法的思想是不变的。

图的广度优先遍历

广度优先搜索(Breadth First Search) 简称广搜或者 BFS,是遍历图存储结构的一种算法,既适用于无向图 (网),也适用于有向图 (网)。

所谓图的遍历,简单理解就是逐个访问图中的顶点,确保每个顶点都只访问一次。

首先通过一个样例,给大家讲解广度优先搜索算法是如何实现图的遍历的 .

使用广度优先搜索算法,遍历图 1 中无向图的过程是

1 . 初始状态下,图中所有顶点都是尚未访问的,因此任选一个顶点出发,开始遍历整张图。
比如从 V1 顶点出发,先访问 V1:

2 . 从 V1 出发,可以找到 V2 和 V3,它们都没有被访问,所以访问它们:

注意:本图中先访问的是 V2,也可以先访问 V3。当可以访问的顶点有多个时,访问的顺序是不唯一的可以根据找到各个顶点的先后次序依次访问它们。后续过程也会遇到类似情况,不再重复赘述。

3 . 根据图 3 中的顶点访问顺序,紧邻 V1 的顶点已经访问过,接下来访问紧邻 V2 的顶点从 V2 顶点出发,可以找到 V1、V4 和 V5,尚未访问的有 V4 和 V5,因此访问它们:

4 . 根据图 4 中的顶点访问顺序,接下来访问紧邻 V3 的顶点从 V3 顶点出发,可以找到 V1、V6 和 V7,尚未访问的有 V6 和 V7,因此访问它们:

5 . 根据图 5 中的顶点访问顺序,接下来访问紧邻 V4 的顶点从 V4 顶点出发,可以找到 V2 和 V8,只有 V8 尚未访问,因此访问它:

6 . 根据图 6 的顶点访问顺序,接下来访问紧邻 V5 的顶点

观察图 6 中的无向图不难发现,与 V5 紧的 V2 和 V8 都已经访问过,无法再找到尚未访问的顶点。此时,广度优先搜索算法会直接跳过 V5,继续从其它的顶点出发。

7 . 广度优先搜索算法先后从 V6、V7、V8 出发,寻找和它们紧邻、尚未访问的顶点,但寻找的结果都和 V5 一样,找不到符合要求的顶点。

8 . 自 V8 之后,访问序列中再无其它顶点,意味着从 V1 顶点出发,无法再找到尚未访问的顶点。这种情况下,广度优先搜索算法会从图的所有顶点中重新选择一个尚未访问的顶点,然后从此顶点出发,以同样的思路继续寻找其它尚未访问的顶点。

所谓广度优先搜索,就是从图中的某个顶点出发,寻找紧邻的、尚未访问的顶点,找到多少就访问多少然后分别从找到的这些顶点出发,继续寻找紧邻的、尚未访问的顶点。

当从某个顶点出发,所有和它连通的顶点都访问完之后,广度优先搜索算法会重新选择一个尚未访问的顶点(非连通图中就存在这样的顶点),继续以同样的思路寻找未访问的其它顶点。直到图中所有顶点都被访问,广度优先搜索算法才会结束执行。


这期就到这里 , 下期见!

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

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

相关文章

C语言之scanf浅析

前言&#xff1a; 当有了变量&#xff0c;我们需要给变量输入值就可以使用scanf函数&#xff0c;如果需要将变量的值输出在屏幕上的时候可以使用printf函数&#xff0c;如&#xff1a; #include <stdio.h> int main() {int score 0;printf("请输⼊成绩:");sc…

软件工程总复习笔记

软件工程课程复习提纲 文章目录 软件工程课程复习提纲一、基本知识点1. 软件工程的概念及目标2. 软件危机的概念及典型表现3. 瀑布模型的概念及特点4. 快速原型模型的特点5. 螺旋模型的基本思想6. 软件生命周期的概念及划分为哪几个阶段7. 软件需求的定义8. 常见的软件需求获取…

Java位运算及移位运算

java中能表示整数数据类型的有byte、short、char、int、long&#xff0c;在计算机中占用的空间使用字节描述&#xff0c;1个字节使用8位二进制表示。 数据类型字节数二进制位数表示范围默认值byte18-27 – 27-10char2160 – 216-1\u0000 (代表字符为空 转成int就是0)short216-…

OpenCV-12绘制图像

OpenCV提供了许多绘制图像的API&#xff0c;可以在图像上绘制各种图形&#xff0c;例如直线&#xff0c;矩形&#xff0c;圆&#xff0c;椭圆等图形。 一、画直线 利用API line&#xff08;img, pt1, pt2, color, thickness, lineType, shift&#xff09;可以绘制直线。 其中…

玩转贝启科技BQ3588C开源鸿蒙系统开发板 —— 代码下载(1)

本文主要参考&#xff1a; BQ3588C_代码下载 1. 安装依赖工具 安装命令如下&#xff1a; sudo apt-get update && sudo apt-get install binutils git git-lfs gnupg flexbison gperf build-essential zip curl zlib1g-dev gcc-multilib g-multiliblibc6-dev-i386 l…

【编译原理】期末预习做题向I

新的一年希望可以成为更好的人嘿嘿&#xff01; 这一篇基本就是把 up 讲的题都截了一遍然后加了点自己的笔记啥的 O.o &#xff08;不妥的话会删掉的 qwq&#xff0c;希望没事嘿嘿&#xff09; 来源&#xff1a;混子速成 I. 绪论 记住组成部分 II. 前后无关文法和语言 1.…

Python从入门到网络爬虫、自动化

可以创建C、C#、Python、Golang、Java、React、Node、Vue、PHP项目 创建Java项目 创建Python项目 简单if……else……语句 # 简单的if……else……语句 state True if state:print("状态正常") else:print("状态异常")# 复杂的if……elif……语句 score …

一骑绝尘!维乐携手骑行侠客轻风逆旅带你解锁冬日逆旅

是逆风冬旅还是冻旅&#xff1f;冬日似乎都被骑友们默认做事应该闭关闭的时间了&#xff0c;空气中萧瑟的寒风仿佛是穿透我们的骨膜&#xff0c;当我还在路上瑟瑟发抖的时候&#xff0c;此时一位公路骑行侠正在开启他的冬日旅途~      以下是来自他的自诉&#xff1a;   …

saas 多租户系统数据隔离方案

关注WX公众号&#xff1a; commindtech77&#xff0c; 获得数据资产相关白皮书下载地址 1. 回复关键字&#xff1a;数据资源入表白皮书 下载 《2023数据资源入表白皮书》 2. 回复关键字&#xff1a;光大银行 下载 光大银行-《商业银行数据资产会计核算研究报告》 3. 回复关键字…

【STM32F103】SysTick系统定时器延时函数

SysTick SysTick是Cortex-M3内核中的一个外设&#xff0c;内嵌在NVIC中&#xff0c;叫系统定时器。 当处理器在调试期间被喊停时&#xff0c;SysTick也将暂停运作。 一共有四个寄存器&#xff0c;不过我们通常用前三个&#xff0c;不需要校准。下图出自《STM32F10xxx Cortex…

关于SIC 的Know-how

SiC的分类和用途 根据电阻率不同&#xff0c;SiC衬底晶片可分为导电型和半绝缘型。 SiC衬底晶片主要用来做成高压功率器件和高频功率器件。其中&#xff0c;导电型SiC衬底晶片经过SiC外延后&#xff08;SiC基SiC外延片&#xff09;&#xff0c;主要应用于制造耐高温、耐高压的…

72内网安全-域横向CSMSF联动及应急响应知识

拿到才行&#xff0c;拿不到就是多余的 案例一MSF&CobaltStrike 联动 Shell 有一些功能可能cs或者msf强大一些&#xff0c;他们两个可以相互调用&#xff0c;在真实情况下也是可以cs和msf同时启动的&#xff0c; cs移交给msf .创建Foreign监听器 “Listeners”“Add”…

蓝桥杯一维差分 | 算法基础

⭐简单说两句⭐ ✨ 正在努力的小新~ &#x1f496; 超级爱分享&#xff0c;分享各种有趣干货&#xff01; &#x1f469;‍&#x1f4bb; 提供&#xff1a;模拟面试 | 简历诊断 | 独家简历模板 &#x1f308; 感谢关注&#xff0c;关注了你就是我的超级粉丝啦&#xff01; &…

Python-docx 深入word源码 带有序号的段落无法设置段后、段前距离、间距等段落属性

如果使用p doc.add_paragraph(内容, styleList Number)来创建序号段落&#xff0c;会发现设置序号段落之间的段前、段后以及段落间距无法生效。后来将docx库生成的word文档打开后发现段落的设置出现问题&#xff0c;如下图红框所示&#xff0c;将该选项去掉即可使段落间距属性…

【AIGC-图片生成视频系列-4】DreamTuner:单张图像足以进行主题驱动生成

目录 一. 项目概述 问题&#xff1a; 解决&#xff1a; 二. 方法详解 a) 整体结构 b) 自主题注意力 三. 文本控制的动漫角色驱动图像生成的结果 四. 文本控制的自然图像驱动图像生成的结果 五. 姿势控制角色驱动图像生成的结果 2023年的最后一天&#xff0c;发个文记录…

迈向通用异常检测和理解:大规模视觉语言模型(GPT-4V)率先推出

PAPERCODEhttps://arxiv.org/pdf/2311.02782.pdfhttps://github.com/caoyunkang/GPT4V-for-Generic-Anomaly-Detection 图1 GPT-4V在多模态多任务异常检测中的综合评估 在这项研究中&#xff0c;我们在多模态异常检测的背景下对GPT-4V进行了全面评估。我们考虑了四种模式&#…

BikeDNA(二) OSM数据的内在分析1

BikeDNA&#xff08;二&#xff09; OSM数据的内在分析1 该笔记本分析给定区域的 OSM 自行车基础设施数据的质量。 质量评估是“内在的”&#xff0c;即仅基于一个输入数据集&#xff0c;而不使用外部信息。 对于将 OSM 数据与用户提供的参考数据集进行比较的外在质量评估&…

mysql原理--optimizer trace表的神器功效

1.概述 设计 MySQL 的大叔提出了一个 optimizer trace 的功能&#xff0c;这个功能可以让我们方便的查看优化器生成执行计划的整个过程&#xff0c;这个功能的开启与关闭由系统变量 optimizer_trace 决定。 如果想打开这个功能&#xff0c;必须首先把 enabled 的值改为 on &am…

力扣回溯算法-电话号码的字母组合

力扣第17题&#xff0c;电话号码的字母组合 题目 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 .电话号码的字母组合 示例: 输入&#xff1a;“2…

lv14 注册字符设备 3

1 注册字符设备 1.1 结构体介绍 struct cdev {struct kobject kobj;//表示该类型实体是一种内核对象struct module *owner;//填THIS_MODULE&#xff0c;表示该字符设备从属于哪个内核模块const struct file_operations *ops;//指向空间存放着针对该设备的各种操作函数地址str…