图的遍历概述

梳理下图这种数据结构的遍历实现

图的遍历

从图中某一顶点出发访遍图中其余顶点,且使每一个顶点仅被访问一次。这一过程就叫做图的遍历(Traversing Graph)。图的遍历算法是求解图的连通性问题、拓扑排序和求关键路径等问题的基础。通常有两种遍历图的方法:深度优先遍历(Depth First Search, DFS)和广度优先遍历(Breadth First Search, BFS)。

深度优先遍历

深度优先遍历,也称深度优先查找、深度优先搜索等。假设初始状态时图中所有顶点都未曾被访问,则深度优先遍历算法从图中某个顶点(任一顶点)出发,访问此顶点并把该顶点标记为已访问,然后依次从该顶点邻接的未被访问的顶点出发,深度优先遍历图,直至图中所有和该顶点有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选图中一个未被访问的顶点作为起始点,重复上述过程,直至图中所有顶点都被访问到为止。

伪代码实现

假设图G(V, E)表示要遍历的图,深度优先遍历的伪代码实现如下:

使用邻接矩阵或邻接表表示图G(V, E)
使用visited[VertexCount]数组记录顶点是否已被访问,其中true表示已访问,false表示未访问
for i=0;i<VertexCount;i++ then
    visited[i] = false
for each vertex v in V then
    if(v is not visited) then
        dfs(v)
dfs(v)
    visited[v] = true
    for(each vertex w in v's adjacent V') then
        if(w is not visited) then
            dfs(w)

该算法的输入规模与图的顶点个数|V|和边的个数|E|有关。由于该算法的递推关系式不容易表示,所以在计算其算法效率时换一种思路。宏观上,在遍历图时,对图中的每个顶点至多调用一次递归,因为一旦某个顶点被标记为已被访问,就不基于该节点去遍历。因此,遍历图的过程实质上就是对每个顶点查找邻接点的过程。所以,不同的存储结构,其算法效率不同。对于使用二维数组表示的邻接矩阵时,查找每个顶点的邻接点所需的时间为 O ( ∣ V ∣ 2 ) O(|V|^2) O(V2)。而当使用邻接表时,由于临邻接点可以使用链表存储,所以查找每个顶点的邻接点所需的时间为 O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|) O(V+E)

广度优先遍历

广度优先遍历,也称广度优先查找、广度优先搜索等。假设初始状态时图中所有顶点都未曾被访问,则广度优先遍历算法从图中某个顶点(任一顶点)出发,访问此顶点并依次访问该顶点的各个未曾访问过的邻接点。然后,分别从这些邻接点出发依次访问他们的临邻接点,并使"先被访问的顶点的邻接点"先于"后被访问的顶点的邻接点"被访问,直至图中所有已被访问的顶点的邻接点都被访问到。若此时图中尚有顶点未被访问,则另选图中一个未被访问的顶点作为起始点,重复上述过程,直至图中所有顶点都被访问到为止。
换句话说,广度优先遍历的过程是以任一顶点开始,由近及远,依次访问和该顶点路径相通且路径长度为1,2,3,…的顶点。

伪代码实现

假设图G(V, E)表示要遍历的图,广度优先遍历的伪代码实现如下:

使用邻接矩阵或邻接表表示图G(V, E)
使用visited[VertexCount]数组记录顶点是否已被访问,其中true表示已访问,false表示未访问
for i=0;i<VertexCount;i++ then
    visited[i] = false
for each vertex v in V then
    if(v is not visited) then
        bfs(v)
bfs(v)
    visited[v] = true
    add v to Queue
    while the Queue is not empty then
        for(each vertex w in v's adjacent V') then
            if(w is not visited) then
                visited[v] = true 
                add w to the Queue
        remove the first vertex from the Queue

广度优先遍历的效率和深度优先遍历的效率是相同的。对于使用二维数组表示的邻接矩阵时,查找每个顶点的邻接点所需的时间为 O ( ∣ V ∣ 2 ) O(|V|^2) O(V2)。而当使用邻接表时,由于临邻接点可以使用链表存储,所以查找每个顶点的邻接点所需的时间为 O ( ∣ V ∣ + ∣ E ∣ ) O(|V| + |E|) O(V+E)

参考

《数据结构 严蔚敏 吴伟民 著
《算法设计与分析基础》 第三版 Anany Levitin 著 潘彦 译
https://blog.csdn.net/qq_40310148/article/details/106786652 图的深度优先遍历(DFS)
https://leetcode-cn.com/circle/article/YLb5l4/ 图文详解 BFS, DFS
https://blog.csdn.net/qq_41170102/article/details/105043114 leetcode高频题笔记之DFS和BFS

猜你喜欢

转载自blog.csdn.net/wangxufa/article/details/133991041