图之 BFS && DFS

128 阅读3分钟

「这是我参与2022首次更文挑战的第27天,活动详情查看:2022首次更文挑战

上篇简单介绍一下图的数据结构的几种构成方式,图跟树一样都是可以进行遍历的,今天就来简单介绍一下图的两种遍历方式 —— 广度优先 && 深度优先

图的遍历:从图的任一节点为起始点出发,通过某种搜索方式,访问图中的所有节点

图之广度优先(BFS)

  • 别称:宽度优先搜索
  • 搜索过程:
    • 任一节点为源点出发
    • 一次性访问邻接点中未被访问过的节点
    • 依次以这些已访问过的邻接点为源点出发,一层一层地去继续访问未被访问访问过的节点
  • 广度优先遍历是按照广度优先搜索的方式对图进行遍历
    • 先被访问的节点,它的邻接点会被优先访问到(可通过队列来实现先进先出的访问顺序)
    • 算法步骤:
      • 初始化【 所有节点的状态设置为未被访问 + 空队列 】
      • 任一节点(v)为起始点【 访问 + 标记为已被访问 + v 入队 】
      • 队列非空——继续;队列为空——结束
      • 队头元素(v)出队 -> v 的所有未被访问的邻接点【 依次访问 + 标记为已被访问 + 邻接点入队 】-> 继续上一步
    • 基于邻接矩阵的广度优先遍历
      • 每个节点的邻接点时间复杂度O(n) + 总时间复杂度O(n^2)
      • 辅助队列【 每个节点入队一次 + 空间复杂度O(n) 】
    • 基于邻接表的广度优先遍历
      • 查找邻接点的时间复杂度O(e) + 初始化O(n) => 总的时间复杂度O(n+e)
      • 同上

图之深度优先(DFS)

  • 搜索过程:
    • 找到一条路径 -> 沿着路径一直搜索 -> 至无法搜索时 -> 回退到刚刚访问的节点
  • 深度优先遍历时按照深度优先搜索的方式对图进行遍历
    • 后被访问的节点,它的邻接点会被优先访问到(可通过栈来实现先进后出的访问顺序——递归是通过栈实现的)
    • 算法步骤:
      • 初始化【 所有节点的状态设置为未被访问 】
      • 任一节点(v)为起始点【 访问 + 标记为已被访问 】
      • 一次检查节点的所有邻接点(w)【 w 未被访问 -> 以 w 为起始点 -> 继续遍历(通过递归调用上一步) 】
    • 基于邻接矩阵的深度优先遍历
      • 每个节点的邻接点时间复杂度O(n) + 总时间复杂度O(n^2)
      • 通过递归栈【 空间复杂度O(n) 】
    • 基于邻接表的深度优先遍历
      • 查找邻接点的时间复杂度O(e) + 初始化O(n) => 总的时间复杂度O(n+e)
      • 同上

  • 图的邻接矩阵是唯一的
    • 基于邻接矩阵的广度优先遍历和深度优先遍历,得到的序列也是唯一的
  • 图的邻接表是不唯一的
    • 基于邻接表的广度优先遍历和深度优先遍历,得到的序列也不是唯一的

结 —— BFS + DFS 可以帮助我们更好地解决图中的节点的搜索的问题,选对方案,提升程序的搜索效率