【基础算法】DFS和BFS

DFS和BFS都是图的搜素算法
DFS:深度优先搜索,存放候补节点的数据结构是栈(先进后出)
BFS:广度优先搜索,存放候补节点的数据结构是队列(先进先出)

0. 分析

DFS、BFS

  • 我们将顶点1作为搜索的起点。
  • 以广度优先搜索进行分析
    • 1、先寻找1的邻接节点并对其进行搜索,找到231的邻接节点(候补节点),因为BFS是对距离近的顶点(直接相连的顶点)进行搜索,那么思考一下我们需要用什么数据结构存放顶点1的邻接节点23呢?对,答案是使用队列来存放。
    • 2、我们对1进行搜索完毕,并将其的邻接节点23存放队列中,之后我们将从队列中拿出我们即将要搜索的下一个顶点,因为队列是先进先出,所以2出队,对2进行搜索,并将其邻接节点134放入队列中。
    • 3、当前队列元素为3134,取出队首元素3对其进行搜索,并将其邻接节点1245放入队列中。
    • 4、注意:当前队列元素为1341245,取出队首元素1对其进行搜索???1不是我们的搜索起点么,怎么又重新对1进行搜索?
      这是因为我们并没有对已经搜索过的顶点和未被搜索过的顶点进行区分,我们可以为每一个顶点加上一个黑色标记,被搜索过的顶点我们将标记颜色改为白色,这样我们就可以区分出哪些顶点是被搜索过的,哪些是未被搜索过的。(这里我们使用标记f布尔值来区分,已搜索:true,未搜索:false)
      123f都为true,其余顶点的ffalse
    • 重新执行第4步搜索:当前队列元素为1-true3-true4-false1-true2-true4-false5-true,我们弹出13发现已被搜索过,继续弹出队首元素4,其未被搜索,我们对4进行搜索并将其f=true,将其邻接节点23放入队尾。
    • 5、当前队列元素为1-true2-true3-true5-false2-true3-true,依次弹出被搜索过的队首元素123,直到5,对其进行搜索,并将其邻接节点3放入队尾。
    • 6、当前队列元素为2-true3-true3-true,依次弹出队首元素233发现全部被搜索过,此时队列为空,搜索结束。

感觉怎么样?BFS你已经学会了。也并没有什么难度吧。
那我们总结一下BFS吧:

  • 存放BFS顶点的数据结构:队列
  • 搜索的结束条件:队列为空
  • 怎么区分顶点是否被搜索过:对顶点加上一个标记,通过对标记的判断来区分

BFS结束,DFS学起来还会很难么?自己画个图尝试一下吧~

1. 广度优先搜索

代码实现:

public static <T> void bfs(Vertex<T> vertex) {
        // 创建队列,用来作为临时存储顶点的空间
        ArrayBlockingQueue<Vertex<T>> queue = new ArrayBlockingQueue<Vertex<T>>(8);
        // 将顶点存到队列中
        queue.add(vertex);
        // 如果队列不为空,就进行搜索
        while (!queue.isEmpty()) {
            // 让队列中第一个顶点出队
            Vertex<T> e = queue.poll();
            // 如果该顶点没有被访问过就进行搜索
            if (!e.isVisited){
                System.out.print(e.data+" -> ");
                e.isVisited=true;
                // 如果该顶点有邻接节点,就将邻接节点全部放入队列中
	            if (e.neighList!=null){
	                queue.addAll(e.neighList);
	            }
            }
            
        }
    }

2. 深度优先搜索

代码实现:

public static <T> void dfs(Vertex<T> vertex) {
        // 创建一个栈用来当做临时存储空间
        Stack<Vertex<T>> stack = new Stack<>();
        // 将顶点压入栈中
        stack.push(vertex);
        // 如果栈不为空,就进行搜索
        while (!stack.isEmpty()) {
            // 将栈中第一个元素弹出
            Vertex<T> e = stack.pop();
            // 判断该顶点是否被访问过
            if (!e.isVisited) {
                System.out.print(e.data + " -> ");
                // 标记已被访问
                e.isVisited = true;
                // 判断该顶点是否有邻接节点
	            if (e.neighList != null) {
	                // 将该顶点的所有邻接节点压入栈中
	                stack.addAll(e.neighList);
	            }
            }
            

        }

    }

用到的顶点数据结构:

public static class Vertex<T> {
        // 顶点的值
        private T data;
        // 顶点的邻接节点
        private List<Vertex<T>> neighList;
        // 判断是否被访问过的标记
        private boolean isVisited;

        public Vertex(T data) {
            this.data = data;
        }
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值