BFS(讲解)

本篇节选自OI wiki

引入

DFS 全称是 Depth First Search ,中文名是深度优先搜索,是一种用于遍历或搜索树或图的算法.所谓深度优先,就是说每次都尝试向更深的节点走.该算法讲解时常常与 BFS 并列,但两者除了都能遍历图的连通块以外,\color{red}{用途完全不同,很少有能混用两种算法的情况.}DFS 常常用来指代用递归函数实现的搜索,但实际上两者并不一样.

过程

DFS 最显著的特征在于其 \color{red}{ 递归调用自身} .同时与 BFS 类似,DFS 会对其访问过的点打上访问标记,在遍历图时跳过已打过标记的点,以确保 每个点仅访问一次.符合以上两条规则的函数,便是广义上的 DFS.具体地说,DFS 大致结构如下:

DFS(v) // v 可以是图中的一个顶点,也可以是抽象的概念,如 dp 状态等.
  在 v 上打访问标记
  for u in v 的相邻节点
    if u 没有打过访问标记 then
      DFS(u)
    end
  end
end

以上代码只包含了 DFS 必需的主要结构.实际的 DFS 会在以上代码基础上加入一些代码,利用 DFS 性质进行其他操作.

性质

该算法通常的时间复杂度为 𝑂(𝑛 +𝑚),空间复杂度为 𝑂(𝑛)O(n),其中n 表示点数,𝑚表示边数.注意空间复杂度包含了栈空间,栈空间的空间复杂度是 𝑂(𝑛)的.

栈实现

DFS 可以使用 \color{red}{栈(Stack)} 为遍历中节点的暂存容器来实现;这与用 队列(Queue) 实现的 BFS 形成高度对应.


vector<vector<int>> adj;  // 邻接表
vector<bool> vis;         // 记录节点是否已经遍历

void dfs(int s) {
  stack<int> st;
  st.push(s);
  vis[s] = true;

  while (!st.empty()) {
    int u = st.top();
    st.pop();

    for (int v : adj[u]) {
      if (!vis[v]) {
        vis[v] = true;  // 确保栈里没有重复元素
        st.push(v);
      }
    }
  }
}

递归实现

函数在递归调用时的求值如同对栈的添加和删除元素的顺序,故函数调用所占据的虚拟地址被称为 函数调用栈(Call Stack)

vector<vector<int>> adj;  // 邻接表
vector<bool> vis;         // 记录节点是否已经遍历

void dfs(const int u) {
  vis[u] = true;
  for (int v : adj[u])
    if (!vis[v]) dfs(v)
}

DFS 序列

DFS 序列是指 DFS 调用过程中访问的节点编号的序列.我们发现,每个子树都对应 DFS 序列中的连续一段(一段区间).

一般图上 DFS

对于非连通图,只能访问到起点所在的连通分量.对于连通图,DFS 序列通常不唯一.注:树的 DFS 序列也是不唯一的.在 DFS 过程中,通过记录每个节点从哪个点访问而来,可以建立一个树结构,称为 DFS 树.DFS 树是原图的一个生成树.DFS 树 有很多性质,比如可以用来求 强连通分量

全部评论

相关推荐

昨天 19:50
📍上海·长宁|拼多多总部真实工作全记录✨&nbsp;先看这份「真实福利清单」✨💰&nbsp;薪资与回报:行业竞争力薪资:拼多多的薪资在互联网行业有“天花板级别”的说法。对于技术岗,总包涨幅可观,年终奖通常是重要的组成部分。年终激励:根据公开信息,年终奖通常为4个月工资左右,是年度收入的重要部分。🍱&nbsp;吃在公司,公司管饱:免费三餐+夜宵:公司为员工免费提供早、中、晚三餐,晚上十点后还有夜宵供应。餐食种类丰富,可通过内部APP预订。饮料水果自由:办公区提供多种饮料(可乐、雪碧、元气森林、三得利、东方树叶等)和水果,全天候供应。🚀&nbsp;你的代码将直面“亿级”战场在这里,你解决的每一个技术问题,都直接服务于数亿用户:核心战场:参与支撑万亿级GMV的电商交易系统,每一行代码都关乎千万消费者的购物体验。技术巅峰:构建支持每秒百万级SKU查询的商品API架构;在618大促期间,处理单日亿级的电子面单调用,峰值达每秒数十万单。全栈挑战:从国内主站到跨境业务Temu,从高并发抢单系统到智能客服,业务场景全面覆盖,技术栈不断演进。🌱&nbsp;在这里成长,没有“舒适区”扁平透明:层级简单,沟通直接,好想法能快速落地验证。技术驱动:面对的是真实的、大规模的技术难题,如如何防止万人并发抢单超卖、如何设计支撑全球业务的高并发架构。清晰的目标:一切围绕业务结果和技术突破,成长路径明确——要么成为解决复杂问题的技术专家,要么成为驱动业务增长的核心骨干。🎯&nbsp;我们寻找这样的“硬核”工程师对用技术解决超大规模、高复杂度问题有强烈的热情和好奇心。有扎实的Java/Go基础,并乐于深入分布式系统、高并发架构、云原生等领域。具备“死磕精神”,对技术有追求,不满足于“能用”,追求“极致”。能适应快节奏、高强度的环境,渴望在一个业务飞速发展、技术挑战巨大的平台上,快速成长,创造影响。📮&nbsp;如何加入这场“硬核”挑战?【拼多多集团-PDD校园招聘】内推链接:https://careers.pddglobalhr.com/campus/grad?t=nZjV6Nsn9m,内推码:nZjV6Nsn9m。期待你的加入!我们一起,无拼不青春!(通过此链接投递计入内推,内推简历优先筛选~)
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务