图的遍历算法
图的遍历
- 1.连通图的深度优先搜索
- 1.1. 递归
- 1.2.非递归
- 2.连通图的广度优先遍历
- 3. 非连通图的深度(广度)优先遍历
1.连通图的深度优先搜索
算法思想:从图中某个顶点vi出发,访问此顶点,然后依次从v1的各个未被访问的邻接点出发进行深度优先搜索来遍历图,直至所有与v1所有路径想通的顶点都被访问到为止。
【算法描述】
- 访问顶点v
- 从v的未被访问的邻接点中选取一个顶点w,从w出发进行深度优先遍历,如此深入下去,当某个顶点的所有邻接点都被访问过时,返回上一层,继续上一层中未被访问的顶点进行深度优先遍历,直至图中所有和v有路径想通的顶点都被访问为止
1.1. 递归
【深度遍历递归】
//基于邻接矩阵的连通图的深度优先遍历递归算法
void df_traver_MGraph(const MGraph* G, int v, int visited[])
{//G的存储结构为矩阵,v为出发编号,标志数组已经初始化为0printf("%d ", G->vexs[v]);//访问出发结点visited[v] = 1;//做已访问标记for (int w = 0; w < G->vexNum; w++){//查找和结点v有邻接关系的结点wif (G->arcs[v][w] != 0 && visited[w] == 0)df_traver_MGraph(G, w, visited);}
}
//基于邻接表的连通图的深度优先遍历递归算法
void df_traver_ALGraph(const ALGraph* G, int v, int visited[])
{//G的存储结构为邻接表,v为出发点编号,标记数组已经初始化为0printf("%d ", G->adjlist[v].vertex);//访问出发结点visited[v] = 1;//做已访问标记ArcNode* p = G->adjlist[v].firstArc;//得到边链表的头指针while (p)//查找与v有邻接关系的邻接点{int w = p->adjvex;//w是v的邻接点if (visited[w] == 0)df_traver_ALGraph(G, w, visited);//递归调用p = p->nextArc;}
}
对于先访问的顶点,其深度优先遍历后结束;后访问的顶点,其深度优先遍历先结束。所以,深度优先遍历可以用栈的结构来进行非递归遍历。
关键:是要找进行深度优先遍历的下一个邻接结点的位置。
1.2.非递归
//基于邻接矩阵的连通图的深度优先遍历非递归算法
void df_traver_no_MGraph(const MGraph* G, int v)
{//MGraph是图的邻接矩阵数据类型,从顶点v出发,深度优先遍历连通图Gassert(G);Stack S; StackInit(&S);//创建栈int visited[20] = { 0 };//标记数组,判断结点是否被访问过//初始化标记数组for (int i = 0; i < 20; i++)visited[i] = 0;//访问出发标号为v的结点printf("%d ", G->vexs[v-1]);//设置标号为v的结点已经被访问visited[v] = 1;//出发结点进栈StackPush(&S, v);//寻找v的第一个邻接结点标号int w = FirstAdjVex_MGraph(G, v);while (!StackEmpty(&S))//栈为空的时候,说明所有结点访问{if (w != 0 && visited[w] == 0)//w存在且,标号为w的结点没有被访问过{printf("%d ", G->vexs[w - 1]);visited[w] = 1;StackPush(&S, w);//编号w进栈}else if(w==0)//栈顶出栈{if (StackEmpty(&S))break;v = StackTop(&S);StackPop(&S);w = FirstAdjVex_MGraph(G, v);continue;}w = NextAdjVex_MGraph(G, v, w);//找v的下一个邻接点编号}//销毁栈StackDestroy(&S);
}
/****************************************************/
//基于邻接表的连通图的深度优先遍历非递归算法
void df_traver_no_AlGraph(const ALGraph* G, int v)
{//ALGraph是图的邻接表数据类型,从顶点v出发,深度优先遍历连通图Gassert(G);Stack S; StackInit(&S);//创建栈int visited[20] = { 0 };//标记数组,判断结点是否被访问过//初始化标记数组for (int i = 0; i < 20; i++)visited[i] = 0;//访问出发标号为v的结点printf("%d ", G->adjlist[v-1].vertex);//设置标号为v的结点已经被访问visited[v] = 1;//出发结点进栈StackPush(&S, v);//寻找v的第一个邻接结点标号int w = FirstAdjVex_ALGraph(G, v);while (!StackEmpty(&S))//栈为空的时候,说明所有结点访问{if (w != 0 && visited[w] == 0)//w存在且,标号为w的结点没有被访问过{printf("%d ", G->adjlist[w - 1].vertex);visited[w] = 1;StackPush(&S, w);//编号w进栈}else if (w == 0)//栈顶出栈{if (StackEmpty(&S))break;v = StackTop(&S);StackPop(&S);w = FirstAdjVex_ALGraph(G, v);continue;}w = NextAdjVex_ALGraph(G, v, w);//找v的下一个邻接点编号}//销毁栈StackDestroy(&S);
}//基于领接矩阵,寻找顶点v第一个领接顶点w标号
int FirstAdjVex_MGraph(const MGraph* G, int v)
{assert(G);int j = 0;for (j = 0; j < G->vexNum; j++){if (G->arcs[v - 1][j] != 0)//坐标为第一个非0,说明顶点v和j+1的顶点有联系return j + 1;//返回第一个与顶点v有联系的邻接结点编号,下标+1}return 0;//不存在则返回0
}
//基于邻接矩阵,寻找顶点v的下一个邻接顶点编号
int NextAdjVex_MGraph(const MGraph* G, int v, int w)
{assert(G);int j = 0;for (j = w; j < G->vexNum; j++)//从一个邻接结点编号的下一个编号开始寻找{if (G->arcs[v - 1][j] != 0)//坐标为下一个非0,说明顶点v和j+1的顶点有联系return j + 1;//返回第一个与顶点v有联系的邻接结点编号,下标+1}return 0;//不存在则返回0
}
//基于邻接表,寻找顶点v第一个领接顶点w
int FirstAdjVex_ALGraph(const ALGraph* G, int v)
{assert(G);if (G->adjlist[v - 1].firstArc != NULL){return G->adjlist[v - 1].firstArc->adjvex+1;}return 0;
}
//基于邻接表,寻找顶点v的下一个邻接顶点编号
int NextAdjVex_ALGraph(const ALGraph* G, int v, int w)
{assert(G);ArcNode* p = G->adjlist[v - 1].firstArc;while (p){if (p->adjvex + 1 == w)//找到存放编号为w的边结点break;p = p->nextArc;}if (!p || !p->nextArc)return 0;//没有找到w的下一个邻结点编号else{return p->nextArc->adjvex;}
}
2.连通图的广度优先遍历
算法思想:从图中的某个顶点出发,访问此顶点之后,依次访问v的所有未被访问过的邻接点,之后按这些顶点被访问的先后依次访问它们的邻接结点。
【算法描述】
- 访问初始顶点,并将其顶点编号入队列。
- 队列不为空,则队头顶点编号出队列;依次访问它的每一个未访问过的邻接点,并将其顶点编号入队列。
- 重复2,直至队列为空,遍历结束。
【算法实现】
//基于邻接矩阵的连通图的广度优先遍历算法
void bf_traver_MGraph(const MGraph* G, int v)
{int visited[10] = { 0 };//队列Q存放已经访问过的顶点编号,v为出发点编号Queue Q; QueueInit(&Q);//访问出发结点,将出发结点编号进队列printf("%d ", G->vexs[v - 1]);visited[v] = 1;QueuePush(&Q, v);while (!QueueEmpty(&Q)){int u = QueueFront(&Q); QueuePop(&Q);for (int w = 0; w < G->vexNum; w++)//找出u的所有邻接结点{if (G->arcs[u - 1][w] != 0 && visited[w+1] == 0){printf("%d ", G->vexs[w]);visited[w+1] = 1;QueuePush(&Q, w);}}}
}
//基于邻表的连通图的广度优先遍历算法
void bf_traver_ALGraph(const ALGraph* G, int v)
{int visited[10] = { 0 };//队列Q存放已经访问过的顶点编号,v为出发点编号Queue Q; QueueInit(&Q);//访问出发结点,将出发结点编号进队列printf("%d ", G->adjlist[v - 1].vertex);visited[v] = 1;QueuePush(&Q, v);while (!QueueEmpty(&Q)){int u = QueueFront(&Q); QueuePop(&Q);ArcNode* p = G->adjlist[u - 1].firstArc;while (p != NULL)//找出u的所有邻接点{int w = p->adjvex;//取邻接点编号if (visited[w + 1] == 0){printf("%d ", G->adjlist[w].vertex);visited[w + 1] = 1;QueuePush(&Q, w + 1);}p = p->nextArc;}}
}
3. 非连通图的深度(广度)优先遍历
对每一个未被访问过的顶点进行深度(广度)优先遍历
【算法实现】
//非连通图的深度(广度)优先遍历
void traver(const MGraph* G)
{assert(G);int visited[10] = { 0 };for (int i = 0; i < G->vexNum; i++){if (visited[i] == 0)df_traver_MGraph(G, i, visited);//深度//bf_traver_MGraph(&G, i + 1);广度}
}
相关文章:

图的遍历算法
图的遍历1.连通图的深度优先搜索1.1. 递归1.2.非递归2.连通图的广度优先遍历3. 非连通图的深度(广度)优先遍历1.连通图的深度优先搜索 算法思想:从图中某个顶点vi出发,访问此顶点,然后依次从v1的各个未被访问的邻接点…...

【蓝桥杯集训·每日一题】 AcWing 3996. 涂色
文章目录一、题目1、原题链接2、题目描述二、解题报告1、思路分析2、时间复杂度3、代码详解三、知识风暴区间DPUnique函数一、题目 1、原题链接 3996. 涂色 2、题目描述 有 n 个砖块排成一排,从左到右编号为 1∼n。 其中,第 i 个砖块的初始颜色为 ci。 …...

人工智能中的Web端编程
Java是当前的主流编程语言之一,常年稳居TIOBE编程语言排行榜前五。Java的使用领域非常广泛,包括了桌面端编程、Web端编程、移动端编程等几乎所有的编程领域。Java是Web端编程使用最广泛的编程语言之一。要学习Web端编程,需要了解Java语言的知…...

jsp+mysql+J2EE校园自行车租赁系统cdA1A2程序
本系统的具体功能有以下六项: 1、用户信息管理模块:用户需要注册成为本网站的用户,同时修改自己的用户资料,在必要时修改自己的登陆密码。 2、车辆查询模块:用户可以根据自己的要求,按照不同的查询方式来查询自己想要的…...

当营养遇上肠道菌群:探究其对儿童健康的影响
谷禾健康 越来越多的证据表明,肠道菌群定植紊乱和微生物多样性减少与全球非传染性疾病 (NCD) 的增加有关。影响儿童和青少年的非传染性疾病包括肥胖及其相关合并症、自身免疫性疾病、过敏性疾病和哮喘。饮食变化也与非传染性疾病的发病机制有关,并且由于…...

vue尚品汇商城项目-day01【4.完成非路由组件Header与Footer业务】
文章目录4.完成非路由组件Header与Footer业务4.1使用组件的步骤(非路由组件)本人其他相关文章链接4.完成非路由组件Header与Footer业务 在咱们项目开发中,不在以HTML CSS 为主,主要搞业务、逻辑 开发项目的流程: (1)…...

IDEA安装教程(图文详解,一步搞定)
文章目录第一步:官网下载IDEA第二步:卸载旧的IDEA(没有则跳过)第二步:安装IDEA第一步:官网下载IDEA 地址:https://www.jetbrains.com/idea/download/other.html 第二步:卸载旧的I…...

【01 DualCam Porting】
1、配置camera_custom_stero_setting.h a、增加sensor配置 /vendor/mediatek/proprietary/custom/mt6765/hal/camera/camera_custom_stereo_setting.h注意: 1)IMGOYUV Size:在有FOV crop的情况下,不能配置为sensor full size,建议比full size 小或者配置为fov crop的值…...

redis --- string类型的使用
目录 一、string类型使用 1.1、set key value参数解析 1.2、同时设置/获取多个键值 1.3、获取/设置指定区间范围内的值 1.4、数值增减 1.5、获取字符串长度和内容追加 1.6、分布式锁 1.7、getset(先get再set) 一、string类型使用 1.1、set key value参数解析 SET key v…...

康耐视visionpro-机器视觉定位引导-经验总结-来自视觉人粉丝分享
1、机器人吸取电路板,移动到拍照位置,并在电路板上找一个标记点,并且,通过机器人示教把当前电路板能够准确的放入到目标位置。 2、机器人吸取电路板吸取电路板,在x,y方向进行移动,总共移动4个位置ÿ…...

包管理工具npm
一:package.json 在某个文件路径下,执行 npm init。就会生成package.json文件。大致如下: {"name": "test","version": "1.0.0","description": "测试","main": &q…...

ChatGPT正进军各行各业,抓住机遇,拥有无限的可能性。
每一个新技术的出现都会对各行各业产生冲击,但关键在于如何抓住这个机遇。ChatGPT是一项非常具有前途的技术,它可以在许多领域为人们提供更好的服务和体验。这项技术的优势之一是它可以快速而准确地理解和解释自然语言,从而使人们可以更轻松地…...

Maven 多模块管理
多模块管理简单地理解就是一个 Java 工程项目中不止有一个 pom.xml 文件,会在不同的目录中有多个这样的文件,进而实现 Maven 的多模块管理 在多人使用Maven协作开发项目时,尤其是稍微上点规模的项目,每个RD的工作都细分到具体功能…...

crash 内核调试工具 ps 指令 显示的进程状态 RU, IN, UN, ZO, ST, TR, DE, SW, WA, PA 什么意思
crash> help ps | grep "the task state" 5. the task state (RU, IN, UN, ZO ,ST, TR, DE, SW, WA, PA, ID, NE) 参考linux-4.19.113内核源码(include/linux/sched.h),有如下定义 /** Task state bitmask. NOTE! These bits…...

Spring《二》bean的实例化与生命周期
🍎道阻且长,行则将至。🍓 上一篇:Spring《一》快速入门 下一篇:Spring《三》DI依赖注入 目录一、bean实例化🍍1.构造方法 ***2.静态工厂 *使用工厂创建对象实例化bean3.实例工厂 ***使用示例工厂创建对象实…...

java与kotlin 写法区别
原文链接:https://gitcode.net/mirrors/mindorksopensource/from-java-to-kotlin?utm_sourcecsdn_github_accelerator#assigning-the-null-value Print to Console 打印到控制台 Java System.out.print("Amit Shekhar"); System.out.println("Amit…...

服务器运行深度学习代码使用指南
该内容配置均在九天毕昇下配置。 当前系统使用的linux版本为:Ubuntu 18.04 LTS。 当前版本安装的是:cuda10.1。 九天毕昇平台:https://jiutian.10086.cn/edu/#/home 一、linux下运行python的操作 ls 为列出当前目录中的文件 cd 文件名 进入…...

计算机组成原理 - 2. 数据的表示和运算
整理自天勤高分笔记,购书链接: 24 天勤高分笔记 要记住的几个数字 📓: 215327682^{15} 3276821532768 216655362^{16} 6553621665536 23121474836482^{31} 21474836482312147483648 23242949672962^{32} 4294967296232429496…...

【js】基础知识点--语句,break和continue,switch,with,for..in,do-while,while
一、break和continue语句,常用 break 语句会立即退出循环,强制继续执行循环后面的语句。而 continue 语句虽然也是立即退出循环,但退出循环后会从循环的顶部继续执行 var num 0; for (var i1; i < 10; i) {if (i % 5 0) {break;}num; …...

【C++】迭代器
内容来自《C Primer(第5版)》9.2.1 迭代器、9.2.3 begin和end成员、9.3.6 容器操作可能使迭代器失效、10.4.3 反向迭代器 目录 1. 迭代器 1.1 迭代器范围 1.2 使用左闭合范围蕴含的编程假定 2. begin和end成员 3. 容器操作可能使迭代器失效 3.1 编…...

数据可视化在前端中的应用
前端开发中,数据可视化是一种非常重要的技术。它可以将复杂的数据以图形化的方式展示出来,让用户更容易理解和分析数据。在前端中,VUE是一种非常流行的JavaScript框架,可以用来实现各种数据可视化效果。 首先,让我们来看看一些常见的数据可视化方式: 表格:表格是数据可…...

FFmpeg 合并视频文件没声音,不同步原因
查了不少帖子也没搞明白,可能懂的人不会遇到吧。 1 没声音是因为我几个视频文件中,有的没音轨,就是用文字生成了个视频,需要先给它加个dummy的音轨才行。 2 视频不同步是因为各个视频格式不一样,参数挺多我也不知道具…...

绕不开的“定位”
绕开“定位”这个词谈企业战略和品牌 相当于揪住头发离开地球 定位这个词,已经进入商业界的心智中去了 发明这个词的特劳特和里斯的思想有啥差异? 《定位屋》刨析的很到位 趣讲大白话:把握概念的源头,就理解对了大部分 【趣讲信息…...

《Effective Objective-C 2.0 》 阅读笔记 item12
第12条:理解消息转发机制 1. 消息转发机制 当对象接收到无法解读的消息后,就会启动“消息转发”机制,开发者可经由此过程告诉对象应该如何处理未知消息。 消息转发分为两大阶段 第一阶段:先征询接收者所属的类,看其…...

云原生计算能消除技术债务吗?
云原生计算可以将行业领域驱动的设计、GitOps和其他现代软件最佳实践汇总起来,如果企业实施得当,可以减少技术债务。 云原生计算是企业IT的一种新范式,它涉及现代技术的方方面面,从应用程序开发到软件架构,再到保持一…...

9. 回文数
题目 给你一个整数 xxx ,如果 xxx 是一个回文整数,返回 truetruetrue ;否则,返回 falsefalsefalse 。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 例子 输入&am…...

[SV]SystemVerilog线程之fork...join专题
SystemVerilog线程之fork...join专题 Q:fork-join_none开辟的线程在外部任务退出后也会结束吗? A:后台线程不会结束,任何由fork开辟的线程(join、join_any、join_none),无论其外部任务ÿ…...

你看这个spring的aop它又大又宽
aop🚓AOP 分类AspectJ | 高级但是难用Spring AOP | 易用但仅支持方法aop 原理明月几时有,把酒问青天。——唐代李白《将进酒》 AOP 分类 在 Spring Boot 中,AOP 的实现主要有以下几种: 基于 AspectJ 的 AOP:这是一种基…...

设计模式-创建-单例模式
4.1.1 模式介绍 定义 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,此模式保证某个类在运行期间,只有一个实例对外提供服务,而这个类被称为单例类。 作用 保证一个类只有一个实例为该实例提供一个全…...

使用mybatis-plus-generator配置一套适合你的CRUD
1、maven引入 mybatis-plus-generator 和模板引擎,你也可以使用freemarker之类的,看个人 <!-- mybatisplus代码生成器 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactI…...