图:高频面试题-图的广度和深度优先遍历

图的广度优先遍历:指的是从图的一个未遍历的节点出发,先遍历这个节点的相邻节点,再依次遍历每个相邻节点的相邻节点。遍历过程主要使用队列的辅助结构

深度优先遍历:深度优先其实是一个递归过程,类似于树的前序遍历;它从图的某个顶点出发,访问此顶点,然后从该顶点的未被访问的邻接顶点出发深度优先遍历图,直至图中所有和该顶点有路径相通的顶点都被访问到了;若此时图中尚有顶点未被访问,则另选图中一个未曾被访问的顶点做起始点,重复上述过程,直至图中所有顶点都被访问到为止。遍历过程主要使用栈数据结构:

上代码,代码中有详细的注释,大家可以自己试着理解一下:

BFS的代码

package dataStructure.graph;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;

public class GraphBfs {
    public static void bfs(Node start) {
        if(start == null) return;
        //List<Node> nexts = start.nexts;
        Queue<Node>  queue = new LinkedList<>();

        HashSet<Node> visited = new HashSet<>();
        //和二叉树的宽度优先遍历类似,每个节点弹出的时候打印
        //先把开始节点入队
        queue.offer(start);
        //入队之后就是被访问过了,加入visited中表示该节点已被访问
        visited.add(start);
        //只要队列不空
        while(!queue.isEmpty()) {
            //从队列中取出第一个节点(也是队列中现在所有节点中最先被放入的,队列是先进先出的)
            Node node = queue.poll();
            //弹出时打印
            System.out.println(node.value);
            //对于该节点的所有节点进行遍历
            for(Node next : node.nexts) {
                //如果已经被访问过了,直接跳过
                if(!visited.contains(next)) {
                    //没有被访问过的,依次加入队列并标记访问过(放入visited)
                    queue.offer(next);
                    visited.add(next);
                }
            }
        }
    }

    public static void main(String[] args) {
        int[][] matrix = {{1,0,1},{2,0,2},{2,1,2},{2,1,3}};
        Graph graph = GraphGenerator.createGraph(matrix);
        bfs(graph.nodes.get(0));
    }
}

DFS的代码:

package dataStructure.graph;

import java.util.HashSet;
import java.util.Set;
import java.util.Stack;

public class GraphDfs {
    public static void dfs(Node start) {
        if(start == null) return;
        //深度优先遍历使用栈来实现(一条链路走完之后要继续下一条路,需要利用栈的先进后出的特性)
        Stack<Node> stack = new Stack<>();
        //标记所有被访问过的节点
        Set<Node> visited = new HashSet<>();
        //先把起始节点压栈,并打印和标记已访问
        stack.push(start);
        visited.add(start);
        System.out.println(start.value);
        //只要队列不空
        while(!stack.isEmpty()) {
            //弹出最后一个被加入的节点
            Node cur = stack.pop();
            //如果有后序节点,挨个遍历
            for(Node next : cur.nexts) {
                //如果节点已经被访问过了,直接跳过
                //如果发现任意一个没有访问过的节点
                if(!visited.contains(next)) {
                    //把当前节点和遍历到的当前没有遍历过的孩子都压入栈中
                    //把cur再入栈的原因是等next这条路走完的时候再试试cur能不能找到没有遍历过的其他的next
                    stack.push(cur);
                    stack.push(next);
                    //入栈即打印
                    System.out.println(next.value);
                    //标记已访问
                    visited.add(next);
                    //发现任意一条路,这条路要走到头,走到头之前没有必要再尝试其他的路
                    break;
                }
            }
        }
    }

    public static void main(String[] args) {
        int[][] matrix = {{1,0,1},{2,0,2},{2,1,2},{2,1,3}};
        Graph graph = GraphGenerator.createGraph(matrix);
        dfs(graph.nodes.get(0));
    }
}

DFS的过程分析:

 注意看代码注释和图,有不懂的可以私信我,也欢迎批评指正

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值