c++中如何实现深度优先搜索DFS_c++ DFS算法模板

发布时间 - 2026-01-06 00:00:00    点击率:
递归DFS需初始化visited数组并在进入前检查越界和访问状态,非递归DFS用stack模拟并压栈前标记visited,回溯DFS须成对操作状态变量且剪枝前置。

直接用递归实现 DFS 最简洁,但要注意栈溢出和访问标记的时机;非递归版本用 stack 模拟更可控,适合图很大或深度不确定的场景。

递归 DFS:必须初始化 visited 数组并检查边界

递归写法最符合 DFS 直观逻辑,但容易漏掉两个关键点:一是未初始化 visited 数组导致重复访问,二是没在进入递归前检查索引越界或节点合法性。

  • visited 必须在调用 DFS 前清零(如 vector visited(n, false)),不能只在函数内声明
  • 每次递归入口处立刻判断 if (i = n || visited[i]) return;,否则可能越界访问或死循环
  • 邻接表遍历时,对每个 neighbor 都要先检查是否已访问,再递归——顺序不能颠倒

非递归 DFS:用 stack 存节点索引,手动管理状态

stack 替代系统调用栈,能避免深递归导致的栈溢出,也方便在遍历中插入调试逻辑。但需注意:它不等价于“递归的逐行翻译”,而是按压栈顺序反向访问子节点。

  • 压栈前就要标记 visited[node] = true,否则同一节点可能被多次压入
  • 遍历邻接表时,推荐倒序压栈(如从 adj[node].rbegin()rend()),使出栈顺序与递归一致
  • 若需记录路径或深度,可在 stack 中存 pair(节点 + 当前深度)
void dfs_iterative(int start, const vector>& adj) {
    int n = adj.size();
    vector visited(n, false);
    stack st;
    st.push(start);
    visited[start] = true;

    while (!st.empty()) {
        int u = st.top(); st.pop();
        // 处理节点 u
        for (auto it = adj[u].rbegin(); it != adj[u].rend(); ++it) {
            int v = *it;
            if (!visited[v]) {
                visited[v] = true;
                st.push(v);
            }
        }
    }
}

DFS 回溯模板:用于排列、组合、棋盘问题等场景

这类 DFS 的核心不是遍历图,而是探索解空间树;必须配合「进入递归前 push/标记 → 递归返回后 pop/回退」的成对操作,否则状态污染。

  • pathused 是典型状态变量,每次修改都必须可逆
  • 剪枝条件(如 if (path.size() == k))应放在递归入口处,早停节省开销
  • for 循环里从 start 开始(组合)还是从 0 开始(排列),直接影响去重逻辑

图的连通性、拓扑排序、强连通分量这些进阶用途,都建立在基础 DFS 遍历正确性的前提上。最容易被忽略的是:递归版忘记传引用导致 visited 不生效,或者非递归版把 visited 标记位置错放到出栈后——这两个错误会让算法完全失效,且不易调试。


# node  #   # ai  # c++  # 排列  # if  # for  # 递归  # int  # 循环  # 算法  # 遍历  # 的是  # 进阶  # 放在  # 一是  # 并在  # 是从  # 这两个  # 这类 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 品牌网站制作公司有哪些,买正品品牌一般去哪个网站买?  浏览器如何快速切换搜索引擎_在地址栏使用不同搜索引擎【搜索】  Laravel怎么解决跨域问题_Laravel配置CORS跨域访问  Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制  网站制作大概多少钱一个,做一个平台网站大概多少钱?  开心动漫网站制作软件下载,十分开心动画为何停播?  千问怎样用提示词获取健康建议_千问健康类提示词注意事项【指南】  Laravel如何配置和使用队列处理异步任务_Laravel队列驱动与任务分发实例  如何快速上传建站程序避免常见错误?  ,在苏州找工作,上哪个网站比较好?  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  非常酷的网站设计制作软件,酷培ai教育官方网站?  装修招标网站设计制作流程,装修招标流程?  Google浏览器为什么这么卡 Google浏览器提速优化设置步骤【方法】  Laravel怎么实现前端Toast弹窗提示_Laravel Session闪存数据Flash传递给前端【方法】  Laravel如何实现本地化和多语言支持?(i18n教程)  千库网官网入口推荐 千库网设计创意平台入口  如何快速搭建高效简练网站?  晋江文学城电脑版官网 晋江文学城网页版直接进入  如何在建站主机中优化服务器配置?  如何在云主机快速搭建网站站点?  微信小程序 五星评分(包括半颗星评分)实例代码  EditPlus中的正则表达式 实战(1)  Laravel如何实现登录错误次数限制_Laravel自带LoginThrottles限流配置【方法】  *服务器网站为何频现安全漏洞?  SQL查询语句优化的实用方法总结  Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言  如何破解联通资金短缺导致的基站建设难题?  Laravel如何为API编写文档_Laravel API文档生成与维护方法  香港服务器选型指南:免备案配置与高效建站方案解析  如何在搬瓦工VPS快速搭建网站?  JS中页面与页面之间超链接跳转中文乱码问题的解决办法  网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?  Laravel定时任务怎么设置_Laravel Crontab调度器配置  如何挑选最适合建站的高性能VPS主机?  Laravel怎么实现软删除SoftDeletes_Laravel模型回收站功能与数据恢复【步骤】  Laravel如何正确地在控制器和模型之间分配逻辑_Laravel代码职责分离与架构建议  如何在 Go 中优雅地映射具有动态字段的 JSON 对象到结构体  美食网站链接制作教程视频,哪个教做美食的网站比较专业点?  什么是JavaScript解构赋值_解构赋值有哪些实用技巧  Laravel怎么进行数据库回滚_Laravel Migration数据库版本控制与回滚操作  nodejs redis 发布订阅机制封装实现方法及实例代码  Win11怎么关闭专注助手 Win11关闭免打扰模式设置【操作】  javascript基于原型链的继承及call和apply函数用法分析  Laravel事件监听器怎么写_Laravel Event和Listener使用教程  原生JS实现图片轮播切换效果  Laravel Session怎么存储_Laravel Session驱动配置详解  长沙企业网站制作哪家好,长沙水业集团官方网站?  LinuxShell函数封装方法_脚本复用设计思路【教程】  JavaScript如何实现倒计时_时间函数如何精确控制