2019独角兽企业重金招聘Python工程师标准>>>

深度优先搜索

深度优先搜索是对图的一种遍历方式,如命所示,只要有可能,就尽可能的“深入”。以下为《算法导论》中对深度优先搜索的解释:

深度优先搜索总是对最近才发现的结点 v 的出发边进行探索,直到该结点的所有出发边都被发现为止。一旦结点 v 的所有出发边都被发现,搜索则“回溯”到 v 的前驱结点(v 是经过该结点才被发现的),来搜索该前驱结点的出发边。
该过程一直持续到从源结点可以达到的所有结点都被发现为止。如果还存在尚未发现的结点,则深度优先搜索将从这些未被发现的结点中任选一个作为新的源结点,并重复同样的搜索过程。该算法重复整个过程,直到图中的所有结点都被发现。

深度优先搜索的实现

实现深度优先搜索,通常使用递归的方式,也可以是利用栈来实现。
而深度优先搜索可以分为先序,中序,后序,也就是我们所熟悉的树的遍历的方式。这三种方式本质上还是遵循于深度优先搜索的原则,即尽可能的“深入”,不同的是对结点的处理时机,如先序遍历总是先对当前结点进行了处理,再继续遍历,而后序遍历则是遍历到叶子结点才逐步对结点进行处理。
关于树的遍历的知识可以参考 Construct Binary Tree From Preorder and Inorder Traversal Solution 文章中 How to traverse the tree 一节。

以下为参考自《算法导论》的深度优先搜索的伪代码:

# 用于记录时间
time = 0def dfs_visit(graph, u):time = time + 1# 被发现的结点标记为灰色,d 为结点的发现时间u.color = GRAYu.d = timefor v in graph.Adj[u]:if v.color == WHITE:v.p = udfs_visit(graph, v)# 完成处理的结点标记为黑色,f 为结点的结束时间u.color = BLACKtime = time + 1u.f = timedef dfs(graph):# 图的初始化for vertex in graph.V:vertex.color = WHITE# p 为结点的前驱属性vertex.p = Nonefor vertex in graph.V:if vertex.color == WHITE:dfs_visit(graph, vertex)

需要注意的是,我们是对进行深度优先搜索,在初学深度优先搜索的时候,总是会将问题局限为对的搜索,树是图的一种,局限思维往往会导致无法解决问题。

深度

深度优先搜索可以将结点按层划分,也就是遍历的深度,每进行一次递归,就是对下一层结点的访问。
在搜索时记录深度,可以在搜索时确认当前遍历到的结点的一些具体信息。

有以下例题:Find Largest Value in Each Tree Row
该题目就是找出树的每一层的最大值。在遍历时记录了深度,然后让同层结点进行比较即可。以下为解题源码:

# Definition for a binary tree node.
class TreeNode:def __init__(self, x):self.val = xself.left = Noneself.right = Noneclass Solution:def largestValues(self, root):""":type root: TreeNode:rtype: List[int]"""MIN_VALUE = -2**31def dfs(node, depth, res):if depth not in res:res[depth] = MIN_VALUEres[depth] = max(res[depth], node.val)if node.left is not None:dfs(node.left, depth + 1, res)if node.right is not None:dfs(node.right, depth + 1, res)if root is None:return []res = dict()dfs(root, 0, res)return list(res.values())

再看以下例题:Binary Tree Right Side View

这条题目的要求就是找出树每一层的最右结点。同样这需要在遍历时记录深度,而且需要我们能够有逆向思维。
通常对树的深度优先搜索都是采取于先序遍历的方式,也就是在遍历时优先访问左子结点。在这种情况下,树每一层的最右结点可以看作为该层的最后一个结点。
但是这样的问题在于,在递归的情况下,“最后一个”是难以知悉的,当然深度优先搜索可以利用栈去完成,用栈的话可以控制到“最后一个”。
这里就需要逆向的思维,在深度优先搜索中优先访问左子结点,那么每次递归时每一层最先发现的结点即为的最左结点,这时我们反过来,优先访问右子节点即可。
以下为解题源码:

# Definition for a binary tree node.
class TreeNode:def __init__(self, x):self.val = xself.left = Noneself.right = Noneclass Solution:def rightSideView(self, root):""":type root: TreeNode:rtype: List[int]"""def dfs(node, depth, res):if depth not in res:res[depth] = node.valif node.right is not None:dfs(node.right, depth + 1, res)if node.left is not None:dfs(node.left, depth + 1, res)if root is None:return []res = {}dfs(root, 0, res)return list(res.values())

在深度优先搜索中,对深度信息的掌握其实就是对遍历中所在结点的“位置”的掌握,而有时候就需要围绕这个“位置”的信息来进行解决问题。

转载于:https://my.oschina.net/bingzhong/blog/3005037

深度优先搜索知识总结相关推荐

  1. 深度优先搜索_0基础学算法 搜索篇第一讲 深度优先搜索

    0基础学算法 搜索篇第一讲 深度优先搜索 相信绝大多数人对于深度优先搜索和广度优先搜索是不会特别陌生的,如果我这样说似乎你没听说过,那如果我说dfs和bfs呢?先不说是否学习过它们,至少它们的大名应该 ...

  2. c++输出方块_C/C++编程笔记:DFS 深度优先搜索的基本思想,含实例讲解

    采用搜索算法解决问题时,需要构造一个表明状态特征和不同状态之间关系的数据结构,这种数据结构称为结点.不同的问题需要用不同的数据结构描述. 根据搜索问题所给定的条件,从一个结点出发,可以生成一个或多个新 ...

  3. 一文搞懂深度优先搜索、广度优先搜索(dfs、bfs)

    前言 你问一个人听过哪些算法,那么深度优先搜索(dfs)和宽度优先搜索(bfs)那肯定在其中,很多小老弟学会dfs和bfs就觉得好像懂算法了,无所不能,确实如此,学会dfs和bfs暴力搜索枚举确实利用 ...

  4. 一文搞定深度优先搜索(DFS)与广度优先搜索(BFS)【含完整源码】

    写在前面:博主是一位普普通通的19届双非软工在读生,平时最大的爱好就是听听歌,逛逛B站.博主很喜欢的一句话花开堪折直须折,莫待无花空折枝:博主的理解是头一次为人,就应该做自己想做的事,做自己不后悔的事 ...

  5. DAG的深度优先搜索标记

    这是图论的基础知识点,也是学习Tarjan的导学课. 一.知识 对于在图G上进行深度优先搜索算法所产生的深度优先森林Gt,我们可以定义四种边的类型: 1.树边(Tree Edge):为深度优先森林中G ...

  6. ReviewForJob——深度优先搜索的应用

    [0]README 1)本文旨在 介绍 ReviewForJob--深度优先搜索的应用 及其 源码实现 : 2)搜索树的技术分为广度优先搜索 和 深度优先搜索:而广度优先搜索,我们前面利用 广度优先搜 ...

  7. DFS——深度优先搜索基础

    [0]README 0.1) 本文总结于 数据结构与算法分析, 源代码均为原创, 旨在 review DFS--深度优先搜索 的基础知识: [1]深度优先搜索的应用 1.1)深度优先搜索算法描述(转自 ...

  8. 【LeetCode 深度优先搜索专项】不同岛屿的数量 II(711)

    文章目录 1. 题目 1.1 示例 1.2 说明 1.3 提示 1.4 进阶 2. 解法一(深度优先搜索) 2.1 分析 2.2 解答 2.3 复杂度 1. 题目 给定一个 m×nm \times n ...

  9. 深度优先搜索是什么?

    我们知道,计算机的计算速度是比人脑快很多很多很多的...因此计算机可以将人脑无法一一枚举的状态或者说方式在很短的时间内枚举出来从而得出最终答案,于是便产生搜索的算法,实际上也算是暴力枚举吧,只不过是枚 ...

最新文章

  1. 如何将重复的数据标红_python如何处理重复值数据?
  2. 浅谈caffe中train_val.prototxt和deploy.prototxt文件的区别
  3. laravel redis_如何将redis优化
  4. SD卡格式化怎么恢复?只需要五个步骤
  5. 深入浅出:Microsoft分布式事务处理协调器
  6. c语言设计一个按时间片轮转法实现处理器调度的程序,设计一个按时间片轮转法实现处理器调度的程序...
  7. Centos 7 安装 memcached
  8. 未打清分标识处理方式
  9. JMS(三):MessageListener
  10. VSCode打开多个项目文件夹的解决方法
  11. AutoJs学习-TTS抢语音红包
  12. VS2012旗舰版下载地址和安装密钥
  13. srvany把程序作为Windows服务运行
  14. win10创建新的计算机用户名和密码,Win10怎么新建账户 Win10创建新用户图文教程...
  15. #树形dp#洛谷 2014 codevs 1378 jzoj 1486 选课
  16. Android 亮度调节
  17. vue3项目打包优化三步走
  18. MNIST | 基于朴素贝叶斯分类器的0-9数字手写体识别
  19. sealos+rook 部署 kubeSphere+TiDB
  20. ThreadLocal源码解析2.ThreadLocalMap

热门文章

  1. android 毕业设计 文献翻译,android毕业设计外文翻译.doc
  2. iframe 覆盖父页面_一次iframe子页面与父页面的通信
  3. python邮件发送csv附件_Python2.7 smtplib发送带附件邮件报错STARTTLS解决方法
  4. python的类作用_python——类中的self到底的作用及三个应用场景
  5. jquery的ajax查询数据库,用Jquery和Ajax查询Django数据库
  6. hdu 2275 Kiki Little Kiki 1 水题
  7. C和C++的关键字区别
  8. Hadoop官方文档翻译——MapReduce Tutorial
  9. PowerShell_零基础自学课程_8_高级主题:WMI对象和COM组件
  10. 计算输入序列能组成三角形的个数