无向图的深度优先搜索和广度优先搜索

Posted 算法组

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了无向图的深度优先搜索和广度优先搜索相关的知识,希望对你有一定的参考价值。

1
无向图
1
定义
在数学上,一个图(Graph)是表示物件与物件之间的关系的方法,是图论的基本研究对象。一个图看起来是由一些小圆点(称为顶点或结点)和连结这些圆点的直线或曲线(称为边)组成的。
如果给图的每条边规定一个方向,那么得到的图称为有向图,其边也称为有向边。在有向图中,与一个节点相关联的边有出边和入边之分,而与一个有向边关联的两个点也有始点和终点之分。相反,边没有方向的图称为无向图。
某个顶点的度数即为连接它的边的总数。路径或者环的长度为其中所包含的边数。
2
代码
我们可以抽象出以下的表示图的API:
无向图的深度优先搜索和广度优先搜索
Graph的API的实现可以由多种不同的数据结构来表示,最基本的是维护一系列边的集合,如下:
无向图的深度优先搜索和广度优先搜索
还可以使用邻接矩阵来表示:
无向图的深度优先搜索和广度优先搜索
也可以使用邻接列表来表示:
无向图的深度优先搜索和广度优先搜索
由于采用如上方式具有比较好的灵活性,采用邻接列表来表示的话,可以定义如下数据结构来表示一个Graph对象。
无向图的深度优先搜索和广度优先搜索
https://github.com/tclxspy/Articles/blob/master/algorithm/Code/Graph.java
采用以上三种表示方式的效率如下:
无向图的深度优先搜索和广度优先搜索
2
深度优先搜索
1
原理
在谈论深度优先算法之前,我们可以先看看迷宫探索问题。下面是一个迷宫和图之间的对应关系: 迷宫中的每一个交会点代表图中的一个顶点,每一条通道对应一个边。
无向图的深度优先搜索和广度优先搜索
迷宫探索可以采用Trémaux绳索探索法。即:
  • 选择一条没有标记过的通道,在你走过的路上铺一条绳子;
  • 标记所有你第一次路过的路口和通道;
  • 当来到一个标记过的路口时(用绳子)回退到上个路口;
  • 当会退到的路口已经没有可走的通道时继续回退。
图示如下:
无向图的深度优先搜索和广度优先搜索
下面是迷宫探索的一个小动画:
接下来我们看图的搜索方法。
2
代码
定义一个edgesTo变量来后向记录所有到s的顶点的记录,和仅记录从当前节点到起始节点不同,我们记录图中的每一个节点到开始节点的路径。为了完成这一日任务,通过设置edgesTo[w]=v,我们记录从v到w的边,换句话说,v-w是最后一条从s到达w的边。 edgesTo[]其实是一个指向其父节点的树。
https://github.com/tclxspy/Articles/blob/master/algorithm/Code/DepthFirstSearch.java
3
广度优先搜索
1
原理
我们很自然地还经常对下面这些问题敢兴趣。
单点最短路径。给定一幅图和一个起点s,回答“从s到给定目的顶点v是否存在一条路径?如果有,找出其中最短的那条等类似问题。”
解决这个问题的经典方法叫做广度优先搜索。
其主要原理是:
  • 将 s放到FIFO中,并且将s标记为已访问
  • 重复直到队列为空
  • 移除最近最近添加的顶点v
  • 将v未被访问的节点添加到队列中
  • 标记他们为已经访问
广度优先是以距离递增的方式来搜索路径的。
2
代码
https://github.com/tclxspy/Articles/blob/master/algorithm/Code/BreadthFirstSearch.java
4
总结
本文简要介绍了无向图中的深度优先和广度优先算法,这两种算法时图处理算法中的最基础算法,也是后续更复杂算法的基础。它们搜索路径如下:

以上是关于无向图的深度优先搜索和广度优先搜索的主要内容,如果未能解决你的问题,请参考以下文章

图的深度优先搜索与广度优先搜索

深度和广度优先搜索

图解:深度优先搜索与广度优先搜索

深度优先搜索和广度优先搜索

编程实现以邻接表或邻接矩阵为存储结构,图的广度和深度优先搜索

图的广度、深度优先搜索和拓扑排序