一、深度优先搜索(DFS)

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

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

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

3、同理从10开始往上回溯到6, 6 没有除10以外的子节点,再往上回溯,发现3有除6以外的子点7,所以此时会遍历7。从 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。使用栈来将要遍历的节点压栈,然后出栈后检查此节点是否还有未遍历的节点,有的话压栈,没有的话不断回溯(出栈)。

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); } }
}

二、广度优先搜索(BFS)

广度优先遍历,指的是从图的一个未遍历的节点出发,先遍历这个节点的相邻节点,再依次遍历每个相邻节点的相邻节点。上文所述树的广度优先遍历动图如下,每个节点的值即为它们的遍历顺序。所以广度优先遍历也叫层序遍历,先遍历第一层(节点 1),再遍历第二层(节点 2,3,4),第三层(5,6,7,8),第四层(9,10)。

深度优先遍历用的是栈,而广度优先遍历要用队列来实现,我们以下图二叉树为例来看看如何用队列来实现广度优先遍历。

private static void bfs(Node root) { if (root == null) { return; } Queue<Node> stack = new LinkedList<>(); stack.add(root); while (!stack.isEmpty()) { Node node = stack.poll(); System.out.println("value = " + node.value); Node left = node.left; if (left != null) { stack.add(left); } Node right = node.right; if (right != null) { stack.add(right); } }
}

算法(6)深度优先搜索和广度优先搜索相关推荐

  1. Java实现算法导论中图的广度优先搜索(BFS)和深度优先搜索(DFS)

    对算法导论中图的广度优先搜索(BFS)和深度优先搜索(DFS)用Java实现其中的伪代码算法,案例也采用算法导论中的图. import java.util.ArrayList; import java ...

  2. 算法十——深度优先搜索和广度优先搜索

    文章出处:极客时间<数据结构和算法之美>-作者:王争.该系列文章是本人的学习笔记. 搜索算法 算法是作用于数据结构之上的.深度优先搜索.广度优先搜索是作用于图这种数据结构之上的.图上的搜索 ...

  3. 数据结构学习笔记——图的遍历算法(深度优先搜索和广度优先搜索)

    目录 一.图的遍历概念 二.深度优先搜索(DFS) (一)DFS算法步骤 1.邻接表DFS算法步骤 2.邻接矩阵DFS算法步骤 (二)深度优先生成树.森林 (三)DFS的空间复杂度和时间复杂度 三.广 ...

  4. 八数码深度优先搜索_深度优先搜索和广度优先搜索

    深度优先搜索和广度优先搜索 关于搜索&遍历 对于搜索来说,我们绝大多数情况下处理的都是叫 "所谓的暴力搜索" ,或者是说比较简单朴素的搜索,也就是说你在搜索的时候没有任何所 ...

  5. 深度优先搜索和广度优先搜索

    深度优先搜索和广度优先搜索 ​ 在人工智能的运筹学的领域中求解与图相关的应用中,这两个算法被证明是非常有用的,而且,如需高效地研究图的基本性质,例如图的连通性以及图是否存在环,这些算法也是必不可少的. ...

  6. 学会二叉树不知道干啥?二叉树的深度优先搜索和广度优先搜索,我要打十个乃至二十个(打开你的LeetCode撸起来)学练并举

    目录 一. 图解二叉树的深度优先搜索 二. 二叉树的广度优先搜索  (层序遍历) 三. 打开LeetCode 撸起来 至此, 咱多少被刚刚的后序非递归搞得可能有点小晕晕的, 没事,层序简单呀....  ...

  7. 深度优先遍历和广度优先遍历_图与深度优先搜索和广度优先搜索

    什么是图? 图是一种复杂的非线性表结构.由若干给定的点一级任意两点间的连线所构成.图通常用来描述事物之间的特定关系, 代表的就是事物, 线就是事物之间所具有的关系.例如社交网络就是一种典型的图关系, ...

  8. 迷宫问题:深度优先搜索和广度优先搜索

    迷宫问题:深度优先搜索和广度优先搜索 1.深度优先搜索可以使用栈实现,栈顶元素为当前节点 2.当前节点搜索下一节点,判断节点是否走得通,如果走得通任意方向走一步,走不通一直弹出栈内元素,直到走得通 3 ...

  9. 深度优先搜索与广度优先搜索区别和案例

    今天周末,心血来潮打开LeetCode做一道题: https://leetcode-cn.com/problems/number-of-enclaves/ 看到题,我的第一想法是: 从边缘的陆地开始, ...

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

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

最新文章

  1. JZOJ 5405. 【NOIP2017提高A组模拟10.10】Permutation
  2. 一个YII社区学习网站
  3. CentOS下设置vim的tab键为4格
  4. Datawhale组队-pandas(上)基础(自学)
  5. php腾讯云+视频上传失败,腾讯云视频上传和播放尝试总结
  6. Hibernate的缓存机制介绍
  7. 页面之间的跳转与交互
  8. Java Access Specifier (不同的访问修饰符)
  9. C++ ../ ./的区别
  10. 3628、验证回文串
  11. 后缀树后缀数组LCP
  12. Android程序员学WEB前端(12)-JavaScript(3)-正则表达式-Sublime
  13. 微博发布头条文章失去文本样式以及图片
  14. 一个VC编写的虚拟桌面软件
  15. SAS(十二)PROC步
  16. LeetCode 460. LFU缓存
  17. 三线制PT100测正温(篇一)
  18. C++,软开测开,CV岗面试常考知识点
  19. 51单片机PCF8591-AD-DA转换
  20. oracle验证手机号sql,oracle判断手机号码是否合法

热门文章

  1. 下一代大数据处理引擎,阿里云实时计算独享模式重磅发布 1
  2. java开发的岗位职责,写给正在求职的Java开发
  3. Android--初级
  4. 用友U8产成品入库单红字后无法入库
  5. 大二项目实战:使用flutter开发的学生端app【云山印尼语学习辅助平台】
  6. 西门子PT100以太网模块
  7. 云计算与数据中心的误区
  8. 如何真正学到UI设计精髓 好的学习路线是什么
  9. Linux初学者基础命令行(mkdir、rmdir:创建、删除目录)
  10. 洛谷——P1498 南蛮图腾