图的遍历算法
图的遍历
- 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 编…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
在树莓派上添加音频输入设备的几种方法
在树莓派上添加音频输入设备可以通过以下步骤完成,具体方法取决于设备类型(如USB麦克风、3.5mm接口麦克风或HDMI音频输入)。以下是详细指南: 1. 连接音频输入设备 USB麦克风/声卡:直接插入树莓派的USB接口。3.5mm麦克…...
VisualXML全新升级 | 新增数据库编辑功能
VisualXML是一个功能强大的网络总线设计工具,专注于简化汽车电子系统中复杂的网络数据设计操作。它支持多种主流总线网络格式的数据编辑(如DBC、LDF、ARXML、HEX等),并能够基于Excel表格的方式生成和转换多种数据库文件。由此&…...
人工智能 - 在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型
在Dify、Coze、n8n、FastGPT和RAGFlow之间做出技术选型。这些平台各有侧重,适用场景差异显著。下面我将从核心功能定位、典型应用场景、真实体验痛点、选型决策关键点进行拆解,并提供具体场景下的推荐方案。 一、核心功能定位速览 平台核心定位技术栈亮…...
Tauri2学习笔记
教程地址:https://www.bilibili.com/video/BV1Ca411N7mF?spm_id_from333.788.player.switch&vd_source707ec8983cc32e6e065d5496a7f79ee6 官方指引:https://tauri.app/zh-cn/start/ 目前Tauri2的教程视频不多,我按照Tauri1的教程来学习&…...
