图论遍历【.....】
图论遍历方法
定义
从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次,这个访问的过程叫做图的遍历(Traversing Graph)。且图的遍历算法是一个比较基础的算法,前面我们介绍的有向无环图的依赖排序(拓扑排序)、关键路径等算法都需要基于该算法。
广度优先遍历
也称为广度优先搜索(Breadth First Search),它类似于树的分层遍历算法(按树的深度来遍历,深度为1的节点、深度为2的节点...)。其定义如下:
假设从图中某个顶点v出发,在访问了v之后依次访问v的各个未曾访问过的邻接点,然后分别从这些邻接点出发并依次访问它们的邻接点,并使“先被访问的顶点邻接点”先于“后被访问的顶点的邻接点”被访问,直到图中所有所有已被访问的顶点的邻接点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点作起始点重复上述过程,直至图中所有顶点均被访问到为止。
换句话说,广度优先遍历的过程是以v为起始点,由近至远,依次访问和v有路径相通且路径长度为1,2,...的顶点的过程。
下面演示对示例图的广度优先遍历:假设从起始点v1开始遍历,首先访问v1和v1的邻接点v2和v3,然后依次访问v2的邻接点v4和v5,及v3的邻接点v6和v7,最后访问v4的邻接点v8。于是得到节点的线性遍历顺序为:v1 -> v2 -> v3 -> v4 -> v5 -> v6 -> v7 -> v8,即示例图中红色箭头线为其广度优先遍历顺序。
算法分析
从演示示例的推演中,我们可以发现其访问顺序恰好是一个队列的出队和入队的过程:出队的节点即为当前访问的节点,紧接着将其所有的邻接点入队,为下次迭代时将要访问的预备节点。
深度优先遍历
也称为深度优先搜索(Depth First Search),它类似于树的先根遍历(先访问树的根节点)。其定义如下:
假设从图中的某个顶点v出发,访问此节点后,然后依次从v的未被访问的邻接点出发深度优先遍历图,直到图中所有和v有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则选另选一个未曾访问的顶点作为起始点重复上述过程,直至图中的所有节点都被访问到为止。
下面演示对示例图的深度优先遍历:假设从起始点v1开始遍历,在访问了v1后,选择其邻接点v2。因为v2未曾访问过,则从v2出发进行深度优先遍历。依次类推,接着从v4、v8、v5出发进行遍历。在访问了v5后,由于v5的邻接点都已被访问,则遍历回退到v8。同样的理由,继续回退到v4、v2直至v1,此时v1的另一个邻接点v3未被访问,则遍历又从v1到v3,再继续进行下去。于是得到节点的线性顺序为:v1 -> v2 -> v4 -> v8 -> v5 -> v3 -> v6 -> v7,即示例图中红色箭头线为其深度优先遍历顺序。
算法分析
从上述的描述可以看出,深度优先遍历的定义就是一个递归的过程,每次都以当前节点的第一个未曾访问过的邻接点进行深度优先遍历的过程。因此使用递归函数实现该算法是最直观的实现方式,但由于递归的过程是函数栈累积的过程,如果节点数较多,容易造成函数栈的溢出而导致程序崩溃,因此正常生产环境一般会使用一个栈结构(Stack)来存放遍历的节点以模拟函数栈的调用情况,以此避免递归的缺陷。
作者:Sunny_SunShine
欢迎任何形式的转载,但请务必注明出处。
限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix