目录
图的遍历是指从图中的某一顶点出发,按照某种搜索方法沿着图中的边对图中的所有顶点访问一次且仅访问一次。注意到树是一种特殊的图,所以树的遍历实际上也可视为一种特殊的图的遍历。图的遍历算法是求解图的连通性问题、拓扑排列和求关键路径等算法的基础。
图的遍历比树的遍历要复杂得多,因为图的任一顶点都可能和其余的顶点相邻接,所以在访问某个顶点后,可能沿着某条路径搜索又回到该顶点上。为避免同一顶点被访问多次,在遍历图的过程中,必须记下每个已访问过的顶点,为此可以设一个辅助数组visited[]来标记顶点是否访问过。图的遍历算法主要有两种:广度优先搜索和深度优先搜索。
1、广度优先搜索
广度优先搜索(Breadth-First-Search,BFS)类似于二叉树的层序遍历算法。
基本思想:首先访问起始顶点v,接着由v出发,依次访问v中的各个未访问过的邻接顶点w1,w2,...,wi,然后依次访问w1,w2,...,wi的所有未访问过的邻接顶点;再从这些访问过的顶点出发,访问它们所未被访问过的邻接顶点,直至图中所有顶点都被访问过为止。若此时图中尚有顶点未被访问,则另选图中一个未曾被访问过的顶点作为始点,重复上述过程,直至图中所有顶点都被访问到为止。Dijkstra单源最短路径算法和Prim最小生成树算法也应用了类似的思想。
换句话说,广度优先搜索遍历图的过程是以v为起始点,由近至远依次访问和v有路径相同且路径长度为1,2,...的顶点。广度优先搜索是一种分层的查找过程,每向前走一步可能访问一批顶点,不像深度优先搜索那样有往回退的情况,因此它不是一个递归的算法,为了实现逐层的访问,算法必须借助一个辅助对列,以记忆正在访问的顶点的下一层结点。
2、BFS算法的性能分析
无论是邻接表还是邻接矩阵的存储方式,BFS都需要一个辅助对列Q,n个顶点均需入队一次,在最坏的情况下,空间复杂度为O(|V|)。
采用邻接表存储方法时,每个顶点均需搜索一次(或入对一次),故时间复杂度为O(|V|),在搜索任一顶点的邻接点时,每条边至少访问一次,故时间复杂度为O(|E),算法总的时间复杂度为O(|V|+|E|)。
采用邻接矩阵存储方法时,查找每个顶点的邻接点所需的时间为O(|V|),故算法总的时间复杂度为O()。
3、BFS算法求解单源最短路径问题
若图G=(V,E)为非带权图,定义从顶点u到顶点v的最短路径d(u,v)为从u到v的经过边数最少的路径;若从u到v没有通路,则d(u,v)=∞。
使用BFS,我们可以求解一个满足上述定义的非带权图的单源最短路径问题,这是由广度优先搜索总是按照距离由近到远来遍历图中每个顶点的性质决定的。
4、广度优先生成树
在广度遍历的过程中,我们可以得到一棵遍历树,称为广度优先生成树,如下图所示。需要注意的是,一给定图的邻接矩阵存储表示是唯一的,故其广度优先生成树也是唯一的,但由于邻接表存储表示不唯一,故其广度优先生成树也是不唯一的。