图的遍历——深度优先遍历与广度优先遍历

article/2025/9/20 6:56:06

目录

何谓遍历?

图的遍历特点

图的遍历方式

深度优先搜索

过程分析

案例分析:

算法的代码实现

 测试案例:

测试结果如下:

遍历非连通图

算法复杂度分析

额外补充

广度优先搜索

过程分析

辅助队列

算法的代码实现

队列部分

广度搜索部分

测试案例:

测试结果:

非连通图的代码实现

算法复杂度分析


何谓遍历?

        与树的遍历类似,图的遍历指对图中的每一个顶点都访问且仅仅访问一次

图的遍历特点

        与树的遍历以访问到NULL结点为结束标志不同,由于任意一个图的顶点都可能与其他顶点相邻接,即在访问某个顶点后,沿着某条路径一直搜索下去,有可能会回到原来顶点的位置上,即图的回路有可能会对图的遍历造成影响。为了避免这种影响,搜索中都会设置一个辅助数组记录某个顶点是否已被访问过

图的遍历方式

        图的遍历方式分为:深度优先搜索与广度优先搜索,由于图的存储结构不同,会导致搜索算法的设计思路略微不同。在此,用深度优先搜索邻接矩阵存储的无向网,以及用广度优先搜索邻接表存储的无向网。顶点的坐标从0开始。

深度优先搜索

过程分析

        对于一个连通图而言,其深度优先搜索过程如下:

  1. 选取图中某一个顶点为搜索起点,访问该顶点;
  2. 访问该起点的邻接点,并以其邻接点为新的起点,重复上述步骤,直到刚刚访问过的起点不再存在没有被访问过的邻接点
  3. 返回到上一个刚刚被访问过的顶点,紧接着访问其没有被访问过的邻接点
  4. 重复(2)与(3)的步骤,直到所有的顶点都被访问过一遍,搜索结束。

        可见,深度优先搜索类似于树的先序遍历,同样使用递归算法来实现。同时,搜索的顺序结果也是不唯一的

案例分析:

        如图采用深度优先搜索的遍历顶点顺序如下:

  1. 先访问顶点A,紧接着访问顶点A的邻接点B,重复搜索的过程(2)直到访问到顶点I,再也没有邻接点可以访问;
  2. 从顶点I回溯到顶点B,发现B依旧有未被访问的邻接点F,访问顶点F;
  3. 然后回溯到A,发现A依旧有未被访问过的邻接点C,访问顶点C;
  4. 重复搜索的过程(2)直到访问到顶点G,再也没有邻接点可以访问;
  5.  回溯到顶点D,发现D依旧有没被访问过的邻接点H,访问H;
  6. 所有的顶点都被访问过,搜索结束,搜索顶点的顺序如上图所示。

算法的代码实现

AMGraph数据结构链接:http://t.csdn.cn/7SBwO

//文件名:DFS.h
#pragma once
#include<iostream>
using namespace std;
//实现邻接矩阵的搜索算法
void DFS_AM(AMGraph& G, int v);
//遍历非连通图
void DFS_AMTraverse(AMGraph& G);
//文件名:DFS.cpp
include"DFS.h"
#include"AMGraph.h"//深度遍历搜索遍历邻接矩阵
void DFS_AM(AMGraph& G, int v)
{//由于邻接矩阵查找邻接点过于简单,无需再定义Firstvex与Nextvex//访问v结点,并输出其数据cout << "顶点编号为:" << v << "  顶点数据域:" << G.vexs[v] << endl;//并标记该顶点visited[v] = true;for (int i = 0;i < G.vexnum;i++){//查找与v相互连通的顶点if (G.arcs[v][i] != 0 && !visited[i]){DFS_AM(G, i);}}
}

 测试案例:

//文件名为:text.cpp
#include"DFS.h"
#include"AMGraph.h"int main()
{//创建邻接矩阵AMGraph G;CreateUDN(G);//从下标为0号的顶点开始遍历DFS_AM(G,0);return 0;
}

测试结果如下:

遍历非连通图

        只需要对图中的每一个顶点都做一次深度优先搜索即可,添加代码如下:

//文件名为:DFS.cpp
void DFS_AMTraverse(AMGraph& G)
{for (int i = 0;i < G.vexnum;i++){if(!visited[i])DFS_AM(G, i);}
}

算法复杂度分析

        由于遍历邻接矩阵存储的无向图实际就是遍历各个顶点。在邻接矩阵中,访问每一个顶点的所有邻接点都需要扫描n次,对于扫描n个顶点的所有邻接点,扫描总次数为n^2次,因此时间复杂度为O(n^2);由于搜索过程中,借助了辅助数组visited[n],因此空间复杂度为O(n);很明显,邻接矩阵适合稠密图,否则会判断过多无用的非邻接点。

额外补充

        深度优先搜索邻接表的过程与邻接矩阵类似,通过边来找邻接点,然后对该邻接点做深度优先搜索,直到无边位置。如表的顶点数为n,边数为e,那么时间复杂度为O(n+e)。

广度优先搜索

过程分析

        对于一个连通图而言,其广度优先搜索过程如下:

  1. 从图中的某一个顶点v出发,访问v;
  2. 紧接着,访问v的所有未曾访问过的邻接点;
  3. 然后,访问这些邻接点的所有未曾访问过的邻接点,重复上述过程,要求“先被访问的邻接点的邻接点访问”先于“后被邻接点访问的邻接点访问”,直到所有顶点都被访问。

辅助队列

        细细品味,广度优先搜索与二叉树的层序遍历相似,因此可以借助队列实现上述遍历效果:

  1. 先将某个顶点v入队;
  2. 紧接着让v出队并访问该顶点,同时将其所有未曾入队的邻接点入队;
  3. 依照队列顺序,逐一将队列中的顶点出队并访问,同时还需要将出队顶点未曾入队的邻接点入队;
  4. 重复过程(3),直到队列为空,遍历结束

算法的代码实现

ALGraph数据结构链接:    http://t.csdn.cn/uzDhf

队列部分

//文件名为:ALQue.h
#pragma once
#include<iostream>
using namespace std;/*采用队列辅助实现算法先将第一个顶点入队,当其出队时,将其所有邻接点入队,再继续出队入队直到队列为空
*///队列实现
typedef struct ALQue {//随便给个20把,毕竟设为Mvnum太浪费空间了int Que[20];//存放入队的顶点编号int front, rear;int maxsize;    //队列的最大长度
}ALQue;
//入队、出队(需要弹出元素)、判空、初始化
void ALQueinit(ALQue& Q);
//判断是否为空
bool is_emptys(const ALQue& Q);
//判断是否为满
bool is_full(const ALQue& Q);
//入队
void ALQ_Push(ALQue& Q, const int& v);
//出队
void ALQ_Pop(ALQue& Q, int& w);
//文件名:ALQue.cpp
#include"ALQue.h"
#include"ALGraph.h"
//队列函数实现
//初始化
void ALQueinit(ALQue& Q)
{Q.maxsize = Mvnum;Q.front = Q.rear = 0;
}
//判断是否为空
bool is_emptys(const ALQue& Q)
{if (Q.front == Q.rear)return true;elsereturn false;
}
//判断是否为满
bool is_full(const ALQue& Q)
{if ((Q.rear + 1) % Q.maxsize == Q.front){cout << "队列已满" << endl;return true;}elsereturn false;
}
//入队,无需返回值
void ALQ_Push(ALQue& Q, const int& v)
{//v为下标if (is_full(Q)){return;}Q.Que[Q.rear] = v;Q.rear = (Q.rear + 1) % Q.maxsize;
}
//出队
void ALQ_Pop(ALQue& Q, int& w)
{if (is_emptys(Q)){return;}Q.rear--;w = Q.Que[Q.rear];
}
//队列函数实现

广度搜索部分

//文件名为:BFS.h
#include"ALGraph.h"
#include"ALQue.h"
/*算法核心思想:对于连通图而言,先访问第一个顶点,再访问该顶点的所有邻接点,再访问该顶点所有邻接点的所有邻接点,如此循环重复,直到所有的顶点都被遍历
*///广度优先搜索
void BFS_AL(const ALGraph& G, const int v);//遍历非连通图
void BFS_ALTraverse(const ALGraph& G);
//文件名:BFS.cpp
#include"BFS.h"
//广度优先搜索
void BFS_AL(const ALGraph& G,const int v)
{ALQue Q;//创建队列ALQueinit(Q);//访问该顶点并输出其数据域visited[v] = true;//先将顶点v入队,并且将入队视为已被访问的标志ALQ_Push(Q, v);while (!is_emptys(Q)){int u;  //存储顶点编号ALQ_Pop(Q, u);//出队,并将与u相互邻接的顶点入队cout << "顶点编号为:" << u << " 其数据域:" << G.vertices[u].data << endl;//除非查找过程的代码量巨大,否则两个查找函数就显得有点多余//for (w = FirstAdject(G, u);w >= 0;w = NextAdject(G, u, w));ArcNode* p = G.vertices[u].fisrtarc;while (p){//当u的邻接点的还没有入队时,则将其入队if (!visited[p->adjvex]){ALQ_Push(Q, p->adjvex);visited[p->adjvex] = true;}p = p->nextarc;}}
}//遍历非连通图
void BFS_ALTraverse(const ALGraph& G)
{//最坏的情况是所有的顶点的不连通,因此下标需要从0开始for (int i = 0;i < G.vexnum;i++){if(!visited[i])BFS_AL(G, i);}
}

测试案例:

//文件名:test.cpp
#include"BFS.h"int main()
{ALGraph G;CreateUDNal(G);BFS_AL(G, 0);DelUDNal(G);return 0;
}

测试结果:

非连通图的代码实现

         只需要对每一个顶点都做一次广度优先搜索。

//文件名为:BFS.cpp//遍历非连通图
void BFS_ALTraverse(const ALGraph& G)
{//最坏的情况是所有的顶点的不连通,因此下标需要从0开始for (int i = 0;i < G.vexnum;i++){if(!visited[i])BFS_AL(G, i);}
}

算法复杂度分析

        广度优先所搜的本质同样是将每一个顶点都访问一边。对于邻接表的访问而言,需要先依次访问表头结点表中的n个顶点,紧接着访问每一个顶点所在单链表的边,总共有e条边,则访问的边数为2e次(无向网而言),故时间复杂度为O(n+2e)。同时,由于辅助数组的使用,故空间复杂度为O(n);可见,邻接表比较适合稀疏图,算法的复杂度与图的存储结构有关。


http://chatgpt.dhexx.cn/article/CTFwEtOZ.shtml

相关文章

图的深度优先遍历和广度优先遍历

本文参考自《大话数据结构》 文章目录 定义图的存储结构邻接矩阵邻接表 图的遍历深度优先遍历邻接矩阵代码邻接表代码 广度优先遍历邻接矩阵邻接表 最小生成树最短路径算法 定义 图(Graph) 是由顶点的有穷非空集合和顶点之间边的集合组成&#xff0c;通常表示为G(V&#xff0…

深度优先遍历和广度优先遍历

深度优先遍历和广度优先遍历 什么是 深度/广度 优先遍历&#xff1f; 深度优先遍历简称DFS&#xff08;Depth First Search&#xff09;&#xff0c;广度优先遍历简称BFS&#xff08;Breadth First Search&#xff09;&#xff0c;它们是遍历图当中所有顶点的两种方式。 这…

图的遍历(深度优先搜索)

1、深度优先搜索遍历过程 图的深度优先搜索(Depth First Search)&#xff0c;和树的先序遍历比较类似。 它的思想&#xff1a;假设初始状态是图中所有顶点均未被访问&#xff0c;则从某个顶点v出发&#xff0c;首先访问该顶点&#xff0c;然后依次从它的各个未被访问的邻接点出…

图的遍历算法之深度优先遍历(DFS)(C++)

图的深度优先遍历思想是&#xff1a; 从图中某结点出发&#xff0c;访问其某一相邻结点&#xff0c;再访问该结点的相邻结点&#xff0c;直至访问完所有的结点。 形象的比喻就是&#xff1a;一条路走到头&#xff0c;回头再走没走过的路。 可见&#xff0c;深度优先遍历是一…

图的深度优先遍历

一 图遍历介绍 所谓图的遍历&#xff0c;即是对结点的访问。一个图有那么多个结点&#xff0c;如何遍历这些结点&#xff0c;需要特定策略&#xff0c;一般有两种访问策略。 1 深度优先遍历 2 广度优先遍历 二 深度优先遍历基本思想 图的深度优先搜索(Depth First Search…

图的遍历 ——深度优先遍历

图的遍历 ——深度优先遍历 深度优先搜索&#xff08;Depth First Search&#xff0c;DFS&#xff09;是最常见的图搜索方法之一。 深度优先搜索沿着一条路径一直搜索下去&#xff0c;在无法搜索时&#xff0c;回退到刚刚访问过的节点。深度优先遍历是按照深度优先搜索的方式…

二、图的遍历——深度优先遍历

深度优先遍历&#xff0c;也有称为深度优先搜索&#xff0c;简称为DFS。 深度优先遍历其实就是一个递归的过程&#xff0c;它从图中某个顶点ⅴ出发&#xff0c;访问此顶点&#xff0c;然后从V的未被访问的邻接点出发深度优先遍历图&#xff0c;直至图中所有和V有路径相通的顶点…

图的遍历(深度优先遍历DFS,广度优先遍历BFS)以及C语言的实现

遍历的定义&#xff1a; 从已给的连通图中某一顶点出发&#xff0c;沿着一些边访遍图中所有的顶点&#xff0c;且使每个顶点仅被访问一次&#xff0c;就叫做图的遍历&#xff0c;它是图的基本运算&#xff0e; 一:深度优先遍历&#xff08;&#xff24;&#xff26;&#xff…

使用SSM框架上传图片

使用SSM框架上传图片 为了大家方便对照,我上传源码到网盘,有兴趣的自取. ps:其中有一个存储数据的网页,我没删除,可以忽略 链接&#xff1a;https://pan.baidu.com/s/1u24E8mUs4K-raoQgx-ae2A 提取码&#xff1a;java 建数据表 CREATE DATABASE my_resource;USE my_resource…

SSM框架简单介绍

一. SSM框架简介及特征 1.SpringMVC Spring MVC属于SpringFrameWork的后续产品&#xff0c;已经融合在Spring Web Flow 里面。Spring 框架提供了构建 Web 应用程序的全功能 MVC 模块。使用 Spring 可插入的 MVC 架构&#xff0c;从而在使用Spring进行WEB开发时&#xff0c;可…

SSM框架整合详细教程

目录 1. 什么是SSM&#xff1f; 2. SSM整合的时候容器之间如何访问 3. SSM下面的开发步骤 4. SSM整合时候时容易混乱的知识点 1. 什么是SSM&#xff1f; SSM是对三个框架名字的简写&#xff0c;其中第一个S指的是SpringMVC,第二个S指的是Spring&#xff0c;第三个M指的是M…

SSM框架理解

一、作用&#xff1a; 1、 SSM是spingspringMVCmybatis集成的框架。是标准的MVC模式&#xff0c;将整个系统划分为表现层&#xff0c;controller层&#xff0c;service层&#xff0c;DAO层四层。 2、使用spring MVC负责请求的转发和视图管理&#xff0c;spring实现业务对象管理…

SSM框架初探

SSM 框架初探 SSM框架简介对框架的理解为什么使用 SSM 框架 SpringSpringMVCMybatis SSM框架简介 SSM框架一种以java语言作为后端搭建基本语言的应用系统搭建框架。是继SSH(strutsspringhibernate)之后&#xff0c;目前较为主流的Java EE企业级框架&#xff0c;适用于搭建各种大…

SSM框架整合

今天来整合一下SSM三大框架~~ 1、创建一个maven项目 比较简单就不赘述了&#xff0c;创建的时候选择webapp骨架。 用骨架创建的项目&#xff0c;在创建完之后要更新一下web.xml 模板目录&#xff1a;“你的Tomcat安装目录\webapps\ROOT\WEB-INF\web.xml” 2、项目整体结构 按…

SSM框架原理

SSM框架是spring MVC &#xff0c;spring和mybatis框架的整合&#xff0c;是标准的MVC模式&#xff0c;将整个系统划分为表现层&#xff0c;controller层&#xff0c;service层&#xff0c;DAO层四层 使用spring MVC负责请求的转发和视图管理 spring实现业务对象管理&#xff…

SSM框架总结

一&#xff1a;什么是SSM框架&#xff1f; SSM框架是Spring、SpringMVC和MyBatis框架的总结&#xff0c;是比较标准的MVC模式。 标注的SSM框架有四层&#xff1a;dao&#xff08;mapper&#xff09;层、service层、controller层、domain(entity)层。 使用Spring实现业务对象…

SSM框架详解

SSM框架详解 写在前面&#xff1a;当初整理SSM原理时&#xff0c;参考了网上一些前辈的文章&#xff0c;时间久远已经忘记来源&#xff0c;所以文中原理部分如有侵权请联系我删除。 基于SSM框架的仿天猫商城网站电商后台管理系统 本文视频讲解 文章目录 SSM框架详解 一、项…

java ssm框架论文,ssm框架理解

文章简介: SSM框架集简介 spring框架IOC的理解 mybatis框架sqlSessionFactory理解 Tomcat的理解 图解SSM SSM框架常用注解 1.SSM框架集简介 SSM(Spring+SpringMVC+MyBatis)框架集由Spring、MyBatis两个开源框架整合而成(SpringMVC是Spring中的部分内容)。常作为数据源较简单的…

SSM框架详细讲解

SSM框架 文章目录 SSM框架&#xff08;白痴都看完都会&#xff09;介绍SSM框架<原理>一、什么是SSM框架&#xff1f; 1.Spring2.Spring MVC3.Mybatis &#xff08;核心是SqlSession&#xff09;二、代码实战 1.创建配置工程2.代码实战&#xff08;查询记录数&#xff0…

SSM三大框架超详细总结(适合你重新回顾)

目录 1.1 概念 1.2 Mybatis优点 1.3 Mybatis架构 1.4 底层原理 1.5 Mybatis缓存 1.6 常见面试题 2.1 概念 2.2 Spring优点 2.3 Spring架构 2.4 控制反转&#xff08;IOC&#xff09; 2.5 DI依赖注入 2.6 底层原理(常见面试题) 8、如何用基于 Java 配置的方式配置 Spring&#…