图的遍历——BFS和DFS

BFS

BFS(Breadth First Search)广度优先搜索,类似于二叉树的层序遍历,基本思想:首先访问起始顶点v,接着由v出发,依次访问v的各个未访问过的邻接顶点w1,w2,…,wn,然后再依次访问w1,w2,…,wn所有未被访问过的邻接顶点。。。类似的思想还将应用于Dijkstra单源最短路径算法和Prim最小生成树算法。

广度优先搜索是一种分层查找过程,不像深度优先有往回退的情况,所有它不是一个递归算法。通过借助队列,来记忆正在访问的顶点的下一层顶点。

伪代码

bool visited[图的点数];//访问标记数组,访问过为false
void BFS(Graph G){
    visit(
0);//访问起始节点
   
visited[0]=true;
   
Queue queue;
   
queue.add(0);//顶点i入队
   
while(!q.isEmpty()){
        Node node = q.poll()
;//出队
       
for(…){
           
if (!visited[node邻接点])
               
//node的未访问过的邻接节点入队
       
}
    }
}

因为是伪代码,表达算法思想,不符合语法规范。很多涉及到BFS算法思想的都是基于这个上面进行修改。

BFS算法求单元最短路径

最短路径表示图中从u到v最短的边数,这是由BFS算法总是按照距离由近及远来遍历顶点的性质决定的。

void BFSMinDistance(Graph G,int u){
    int dst[] = new int[n];
    for (int i=0;i<n;i++)
        dst[i]=-1;//dst[i]表示从ui的最短路径,-1表示不可达
    dst[u]=0;
    Queue q;
    q.add(u)//u入队
    while(!q.isEmpty()){
        q.poll();
        for(...){
            if (dst[i]!=-1)//!=-1表示可达之前访问过,如果是带权路径,需要计算比较替换
            //node的未访问过的邻接节点入队
        }
    }
}

最短路径例题

网易2017秋招笔试题,跳石板,每块石板的编号从1、2、3…开始编号,在石板上,只能往前跳编号N的约束步(不包含1和N),问从N跳到M最少跳几步(4<=N<=M<=100000)。

分析:

从N跳到M,就是找从N到M的最短路径,例如N的约束包含a,b,c等,那么N到N+a,N+b,N+c的步数就是1,在从N+a往后继续这样跳,步数+1,以此类推。

public static void main(String[] args){
    Scanner sc = new Scanner(System.in);
    int N = sc.nextInt();
    int M = sc.nextInt();
    //dst表示到达i位置的步数,-1表示不可达
    int[] dst = new int[M+1];
    for (int i=N;i<=M;i++){
        dst[i]=-1;//初始化
    }
    dst[N]=0;//N开始,dst[N]0步
    for (int i=N;i<=M;i++){
        if (dst[i]==-1)//如果该位置不可达则直接跳过
            continue;
        for (int j=2;j*2<=i;j++){
            if (i%j==0){//寻找约束,也就是跳的步数
                if (i+j<=M&&dst[i+j]==-1)//如果跳的位置<=M并且该位置未到过
                    dst[i+j]=dst[i]+1;//步数在调过来的基础上+1
            }
        }
    }
    System.out.println(dst[M]);
}

这里没有使用队列,因为按照石板的编号就能依次遍历,不可达的直接跳过,直到M。

 

DFS

DFS(Depth First Search)深度优先搜索,类似于树的先序遍历。这种搜索算法是尽可能“深”地搜索图。基本思想:首先访问图中起始点v,然后访问与v邻接并且未被访问的顶点w1,再访问与w1邻接未被访问的顶点w2,。。。重复该过程。当不能继续访问时,依次退回到最近被访问的顶点,再访问该顶点未被访问的邻接点。

伪代码

很明显,该算法需要借助栈或者通过递归实现。

//通过递归实现
void DFS(Graph G,int v){
    visit(v);
    visited[v]=true;
    while (v有邻接点w){
        if (!visited[w])
            DFS;
    }
}

//通过栈
void DFS(Graph G,int v){
    Stack stack;
    stack.push(v);
    while (!stack.isEmpty()){
        node=stack.pop();
        visit(node);
        visited[node]=true;
        while (node有邻接点w){
            if (!visited[w])
                stack.push(w);
        }
    }
}

 

图的遍历算法可以用来判断图的连通性。

    原文作者:数据结构之图
    原文地址: https://blog.csdn.net/qq407388356/article/details/79714939
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞