图的遍历——DFS和BFS模板(一般的图)

Posted wangkundentisy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图的遍历——DFS和BFS模板(一般的图)相关的知识,希望对你有一定的参考价值。

关于图的遍历,通常有深度优先搜索(DFS)和广度优先搜索(BFS),本文结合一般的图结构(邻接矩阵和邻接表),给出两种遍历算法的模板

1.深度优先搜索(DFS)

#include<iostream>
#include<unordered_map>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<sstream>
#include<set>
#include<map>
using namespace std;
#define VERTEX_SIZE 100 //定义图中顶点数目

bool visited[VERTEX_SIZE];//建立顶点标记数组,用于判断顶点是否已经走过
class Graph{
.... //自定义图结构(邻接矩阵或者邻接表)
};


void DFSTraverse(Graph G)
{
    memset(visited,false,sizeof(visited));//初始化顶点标记数组
    for(int i = 0 ; i < VERTEX_SIZE;i++) //遍历图中的每个连通分量
        if(!visited[i])
            DFS(G,i);
}
void DFS(Graph G,int v)
{
    visited[v] = true;//修改标记
    visit(v);//访问顶点v
    for(int w = FirstAdjVex(G,v); w >= 0;w = NextAdjVex(G,v,w))//寻找顶点v的邻接点
        if(!visited[w])
            DFS(G,w);
}
void visit(int v)
{
   //自定义操作
   ;
}

int main()
{
    ...
}

关于这个模板,有几点需要注意的:

(1)此处的模板适用于以邻接表表示的图结构或者以邻接矩阵表示的图结构,若以邻接表表示的话,时间复杂度为O(n+e);若以邻接矩阵表示的话,时间复杂度为O(n^2)。其中n为图中节点的个数,e为边的个数。

(2)遍历图的限制条件比较少,只要是未访问过(visited[v] == false)就可以进行访问。

(3)寻找顶点v的邻接点那部分代码是伪代码,需要根据图的具体表示结构进行寻找(邻接矩阵找到相应行进行遍历;邻接表遍历相应的单链表)

(4)在函数DFSTraverse()中,加入了个for循环,目的是:如果图是非连通图的话,需要遍历每个连通分支。由此,可以利用DFS来判断图的连通性,如果从某个节点开始遍历(任意节点),能遍历到所有节点的话,俺么这个图就是连通的。相当于在上述模板中把DFSTraverse()函数中的for循环换成单次遍历。(参考《王道》P191)

2.广度优先搜索(BFS)

#include<iostream>
#include<unordered_map>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<sstream>
#include<set>
#include<map>
using namespace std;
#define VERTEX_SIZE 100 //定义图中顶点数目

bool visited[VERTEX_SIZE];//建立顶点标记数组,用于判断顶点是否已经走过
class Graph{
....//自定义图结构(邻接矩阵或者邻接表)
};


void BFSTraverse(Graph G)
{
    memset(visited,false,sizeof(visited));//初始化顶点标记数组
    queue<int> Q;
    for(int i = 0 ; i < VERTEX_SIZE;i++)
        if(!visited[i])
            BFS(G,i,Q);
}
void BFS(Graph G,int v,queue<int> &Q)
{
    visited[v] = true;
    visit(v);//访问顶点v
    Q.push(v);//v入队
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        for(int w = FirstAdjVex(G,u); w >= 0;w = NextAdjVex(G,u,w))//找到顶点w的所有邻接点
            if(!visited[w])//访问w的邻接点,并且访问过后将邻接点入队
            {
                visited[w] = true;
                visit(w);
                Q.push(w);
            }
    }
}
void visit(int v)
{
   //自定义操作
   ;
}

int main()
{
    ...
}

(1)BFS的时间复杂度与DFS是一样的。

(2)BFSTraverse()函数中的for循环和DFSTraverse()中的作用是一样的,都是遍历所有的连通分支,只不过遍历的顺序不同;所以同样可以用BFS来判断图的连通性。

(3)队列存储的顶点都是它们本身已经访问过的但它们的邻接点未被访问过。

以上是关于图的遍历——DFS和BFS模板(一般的图)的主要内容,如果未能解决你的问题,请参考以下文章

快速排序模板秦九昭算法模板深度优先搜索DFS广度优先搜索BFS图的遍历逆元中国剩余定理斯特林公式

图的遍历(bfs+dfs)模板

算法笔记图结构及图的 DFS 和 BFS 介绍

模板 图的遍历 bfs+dfs 图的最短路径 Floyed+Dijkstra

图的深度优先遍历DFS和广度优先遍历BFS(邻接矩阵存储)超详细完整代码进阶版

深度优先遍历 (DFS) 与广度优先遍历 (BFS)