正文开始:

深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath First Search)是图论中两种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷宫),搜索引擎,爬虫等,也频繁出现在 leetcode,高频面试题中。

前言

深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath First Search)是图论中两种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷宫),搜索引擎,爬虫等,也频繁出现在 leetcode,高频面试题中。

本文将会从以下几个方面来讲述深度优先遍历,广度优先遍历,相信大家看了肯定会有收获。

深度优先遍历

  • 深度优先遍历简介
  • 习题演练
  • DFS,BFS 在搜索引擎中的应用

深度优先遍历简历

主要思路是从图中一个未访问的顶点 V 开始,沿着一条路一直走到底,然后从这条路尽头的节点回退到上一个节点,再从另一条路开始走到底…,不断递归重复此过程,直到所有的顶点都遍历完成,它的特点是不撞南墙不回头,先走完一条路,再换一条路继续走。

树是图的一种特例(连通无环的图就是树),接下来我们来看看树用深度优先遍历该怎么遍历。

1、我们从根节点 1 开始遍历,它相邻的节点有 2,3,4,先遍历节点 2,再遍历 2 的子节点 5,然后再遍历 5 的子节点 9。

2、上图中一条路已经走到底了(9是叶子节点,再无可遍历的节点),此时就从 9 回退到上一个节点 5,看下节点 5 是否还有除 9 以外的节点,没有继续回退到 2,2 也没有除 5 以外的节点,回退到 1,1 有除 2 以外的节点 3,所以从节点 3 开始进行深度优先遍历,如下:

3、同理从 10 开始往上回溯到 6, 6 没有除 10 以外的子节点,再往上回溯,发现 3 有除 6 以外的子点 7,所以此时会遍历 7。

4、从 7 往上回溯到 3, 1,发现 1 还有节点 4 未遍历,所以此时沿着 4, 8 进行遍历,这样就遍历完成了。

完整的节点的遍历顺序如下(节点上的的蓝色数字代表):

相信大家看到以上的遍历不难发现这就是树的前序遍历,实际上不管是前序遍历,还是中序遍历,亦或是后序遍历,都属于深度优先遍历。

那么深度优先遍历该怎么实现呢,有递归和非递归两种表现形式,接下来我们以二叉树为例来看下如何分别用递归和非递归来实现深度优先遍历。

1、递归实现

递归实现比较简单,由于是前序遍历,所以我们依次遍历当前节点,左节点,右节点即可,对于左右节点来说,依次遍历它们的左右节点即可,依此不断递归下去,直到叶节点(递归终止条件),代码如下:

public class Solution { private static class Node { /** * 节点值 */ public int value; /** * 左节点 */ public Node left; /** * 右节点 */ public Node right; public Node(int value, Node left, Node right) { this.value = value; this.left = left; this.right = right; } } public static void dfs(Node treeNode) { if (treeNode == null) { return; } // 遍历节点 process(treeNode) // 遍历左节点 dfs(treeNode.left); // 遍历右节点 dfs(treeNode.right); }
}

递归的表达性很好,也很容易理解,不过如果层级过深,很容易导致栈溢出。所以我们重点看下非递归实现。

2、非递归实现

仔细观察深度优先遍历的特点,对二叉树来说,由于是先序遍历(先遍历当前节点,再遍历左节点,再遍历右节点),所以我们有如下思路:

对于每个节点来说,先遍历当前节点,然后把右节点压栈,再压左节点(这样弹栈的时候会先拿到左节点遍历,符合深度优先遍历要求)。

弹栈,拿到栈顶的节点,如果节点不为空,重复步骤 1, 如果为空,结束遍历。

我们以以下二叉树为例来看下如何用栈来实现 DFS。

整体动图如下:

整体思路还是比较清晰的,使用栈来将要遍历的节点压栈,然后出栈后检查此节点是否还有未遍历的节点,有的话压栈,没有的话不断回溯(出栈),有了思路,不难写出如下用栈实现的二叉树的深度优先遍历代码:

/** * 使用栈来实现 dfs * @param root */
public static void dfsWithStack(Node root) { if (root == null) { return; } Stack<Node> stack = new Stack<>(); // 先把根节点压栈 stack.push(root); while (!stack.isEmpty()) { Node treeNode = stack.pop(); // 遍历节点 process(treeNode) // 先压右节点 if (treeNode.right != null) { stack.push(treeNode.right); } // 再压左节点 if (treeNode.left != null) { stack.push(treeNode.left); } }
} 

可以看到用栈实现深度优先遍历其实代码也不复杂,而且也不用担心递归那样层级过深导致的栈溢出问题。

结尾

这就是我理解的深度优先遍历算法啦,如果有不太对的地方,欢迎指出,谢谢。

深度优先遍历(Depth First Search, 简称 DFS)相关推荐

  1. 数据结构与算法(python):广度优先搜索(Breadth First Search,BFS)和深度优先算法(Depth First Search,DFS)

    参考自 MOOC数据结构与算法Python版 目录 一.广度优先搜索 1.1 BFS算法过程 1.2 广度优先搜索算法分析 二.深度优先搜索 2.1 骑士周游 2.1.1 问题定义 2.1.2 构建骑 ...

  2. 华为机试HJ41:称砝码(深度优先遍历dfs-Depth First Search)

    作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 题目描述: 现有一组砝码,重量互不相等,分别为m1,m2,m3-mn: 每种砝码对应的数量为x1 ...

  3. javascript实现的图数据结构的广度优先 搜索(Breadth-First Search,BFS)和深度优先搜索(Depth-First Search,DFS)...

    最后一例,搞得快.三天之内走了一次.. 下一步,面象对像的javascript编程. function Dictionary(){var items = {};this.has = function ...

  4. 深度优先搜索(Depth First Search)、广度优先搜索(Breadth First Search)

    DFS: /* 邻接表存储的图 - DFS */void Visit( Vertex V ) {printf("正在访问顶点%d\n", V); }/* Visited[]为全局变 ...

  5. 图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS)

    图文详解两种算法:深度优先遍历(DFS)和广度优先遍历(BFS) 阅读本文前,请确保你已经掌握了递归.栈和队列的基本知识,如想掌握搜索的代码实现,请确保你能够用代码实现栈和队列的基本操作. 深度优先遍 ...

  6. 深度优先遍历(DFS)和广度优先遍历(BFS)

    深度优先遍历(DFS)和广度优先遍历(BFS) 图的遍历:所谓遍历,即是对结点的访问.一个图有多个结点,如何遍历这些结点,有两种访问策略: 深度优先遍历(Depth First Search, 简称 ...

  7. Python实现深度优先遍历(DFS)和广度优先遍历(BFS)

    一,简介 深度优先遍历(Depth First Search, 简称 DFS) 与广度优先遍历(Breath First Search)是图论中两种非常重要的算法,生产上广泛用于拓扑排序,寻路(走迷宫 ...

  8. Python二叉树的三种深度优先遍历

    Python二叉树的三种深度优先遍历 一.广度优先遍历和深度优先遍历 对二叉树进行遍历(traversal)是指依次对树中每个节点进行访问,在遍历的过程中实现需要的业务. 对树的遍历方式有广度优先遍历 ...

  9. 图——深度优先遍历(DFS)实现有向无环图的逆拓扑排序

    对图的深度遍历与对树的深度遍历思想类似,采用的是递归函数的办法. 如果是非连通图,则DFS遍历所有顶点即可. //Graph 图 //vertex 顶点,用一个int型变量表示//返回有向图G中顶点v ...

最新文章

  1. 电视游戏会是未来客厅娱乐的主角吗?
  2. 结束php语句的正确方法是,2011-2012-1-《PHP网页设计》试卷b
  3. LNMP架构——OpenResty实现缓存前移(到达Nginx前端层面)
  4. 仿即刻的点赞滚动放大波纹图标
  5. android中各属性布局,Android里面各布局的属性定义
  6. 数据中心空调施工工序工艺管理要点
  7. Prime算法生成迷宫
  8. uniapp php接口如何写,uni-app入门教程之接口的基本使用
  9. 《云原生的本手、妙手和俗手》——2022全国新高考I卷作文
  10. 农商银行招聘计算机人员考什么,农商银行招聘考试考什么内容
  11. golang个人整理知识点
  12. ksql整合debezium创建连接器出现500
  13. 【原创】石灰水滴在汽车上自己清洗的方法
  14. Mysql 计算当前日期是本月第几周:一个自定义算法
  15. css调颜色,CSS3 简单的调色板
  16. 马克斯cms,马克斯cms模板,马克斯cms网站开发
  17. html内联样式(表),外部样式表
  18. python实现签到功能_python实现网页自动签到功能
  19. matlab机器人雅可比矩阵实验,机械臂通过雅可比矩阵实现正运动学及逆运动学迭代解(工具:matlab)...
  20. linux下kettle安装部署

热门文章

  1. 腾讯首款元宇宙项目「ZPLAN」曝光,由天美工作室群总裁姚晓光带队
  2. 推荐两款java版开源的MES制造执行系统源码,免费分享
  3. linux给文件赋权限
  4. TDSQL | 张家港行,我是你的“破壁人”
  5. 矩阵的Jordan标准形
  6. winxp计算机无法访问,分享WinXP工作组计算机无法访问的解决方法
  7. 学习OMO游戏管理驾驶舱的设计
  8. 微美全息:布局元宇宙能否赶上“黎明曙光”?
  9. 图像二值化_三角阈值法
  10. 关于微信公账号H5 API 调用的坑 BUG