算法学习笔记——dfs与bfs

笔者语言组织能力不太好,可能需要笔者结合图和思考模拟加以理解,请见谅。

搜索是暴力法的具体体现,列举每种情况或者遍历所有节点(路径)来求解的一种直接,较为通用(如果不限制运行时间)的算法。

对树的搜索

对于一棵树,熟悉的同学知道遍历这棵树一般有三种遍历的方法:前序遍历、中序遍历、后序遍历。但对于今天的搜索来说,遍历到每个点,就只有横向,纵向两种遍历的方法。

纵向的搜索,深度优先搜索,也就是dfs(Depth-first search),它的遍历方法就是从根节点出发,优先访问最左边的儿子节点,也就是先访问最左边的一条链直到底部,此时无法再向下走了就回头往上走,直到访问到有两个及以上儿子的节点,就去访问原链右边第一条的链。(讲的有点抽象,看图理解吧)

简单来讲就是不重复访问的前提下,能向下走就坚决不回头。

横向的搜索,广度优先搜索,就是bfs(Breadth-first search) 。从根节点a出发,访问a的所有儿子节点即b和c,进到第二层,再对第二层从左往右依次遍历所有节点的儿子节点,从而实现遍历。简单地说就是对每一层都从左往右依次遍历完所有节点。

对图的搜索

那对于一张图,dfs与bfs又是如何工作的呢,以底下这张图为例。

现在要从蓝色的点,走到红色的点。

dfs运行的时候,我们一般都会先设置一个方向,比如我在这里设置方向的优先级为:向右走>向下走>向左走>向上走。那么运行时就会以这种路径去访问到终点。(图中绿色路径因为无路可走了,通过递归回头,但实际上并没有重复访问,直到返回到终点底下可以向上走了)

能向右走坚决不向其他方向走,不能向右走就向下走,不能向下走就向左走,都不能就向上走。如此走到终点。

而bfs运行就不一样了,bfs是一圈一圈斜向的往外扩展,还是按层来说,讲起点(蓝点)设置为第一层,将蓝点所能走到的点设置为第二层,再讲第二层所能走到的点设置为第三层……直到走到终点,每一层内部的遍历顺序也是由我们提前设置好的方向优先级规定的。

大致就是这样。

接下来讲一下实现的方式。

代码实现

以下内容主要实现上面图遍历的场景,需要根据题目需求修改代码。

dfs:

主要的实现方法是通过递归。

数组准备:mp用来存图,vis用来记录点(i,j)是否被访问过。

开始访问:从点(x,y)进入,依次走进依据方向优先级规定的点。注意:每访问一个点,一定要更新vis数组。要不然会出现重复访问的情况。

bfs:

主要的实现方式是队列。

数组准备:与dfs相同。

开始访问:将每一个点下层的点存进队列尾部等待访问,每访问一个点记得更新数组,访问完需要把该点从队列之中pop掉。

总结

时间复杂度:都是O(m),m为图中的边的数量。

空间复杂度:都是O(n), n为点的数量。

一些有趣的性质:

dfs因为是递归来实现,运用递归的性质可以实现回溯。经典例题:N皇后问题。

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

回溯法的大致思路:

而bfs,从运行的情况来讲,因为是一层一层往下访问,所以可以找到在最上边的叶子节点,也就是说bfs能查找最短路径,具体就不详细赘述了,感兴趣可以自行了解一下。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值