0

0

C++如何实现深度优先搜索DFS遍历图_C++递归与非递归版本实现【算法】

冰火之心

冰火之心

发布时间:2026-02-15 12:36:13

|

163人浏览过

|

来源于php中文网

原创

递归版dfs必须在递归调用前标记visited[u]=true,否则在无向图或含环有向图中会无限循环或重复访问;visited[i]表示节点i是否已进入当前dfs树。

c++如何实现深度优先搜索dfs遍历图_c++递归与非递归版本实现【算法】

递归版 DFS 为什么必须用 visited 数组标记访问状态

不标记会导致无限循环或重复访问——尤其在无向图或含环有向图中。visited[i] 表示节点 i 是否已被递归进入过(不是“刚被访问”,而是“当前 DFS 树中已存在”)。常见错误是只在打印/处理时设标记,而应在递归调用前就设:

void dfs(int u) {
    visited[u] = true;  // ✅ 必须在此处标记
    cout << u << " ";
    for (int v : graph[u]) {
        if (!visited[v]) {
            dfs(v);  // ❌ 若这里才标记,v 可能被多个邻居重复压入栈
        }
    }
}
若图用邻接表 vector<vector>></vector> 存储,节点编号从 0 开始,visited 大小需与节点数一致。

非递归 DFS 用 stack 实现时,入栈和出栈顺序决定遍历路径

标准非递归 DFS 应模拟递归的“深度优先”行为:每次取栈顶,立即标记为已访问,并将所有未访问邻接点压栈。关键点:

  • 压栈顺序影响结果:若邻接表是 {1,2,3},先压 3 再压 2 最后压 1,则出栈顺序为 1→2→3(即按原顺序遍历)
  • 不能在出栈时才标记——否则同一节点可能被多次压入;必须在压栈前检查 !visited[v],且压栈即标记
  • 不推荐用 stack<pair bool>></pair> 模拟“是否回溯”,那属于 DFS 迭代器写法,不是基础遍历需求
示例核心逻辑:
stack<int> st;
st.push(start);
visited[start] = true;
while (!st.empty()) {
    int u = st.top(); st.pop();
    cout << u << " ";
    for (int v : graph[u]) {
        if (!visited[v]) {
            visited[v] = true;  // ✅ 压栈前标记
            st.push(v);
        }
    }
}

邻接矩阵 vs 邻接表对 DFS 时间复杂度的影响

使用邻接矩阵(vector<vector>></vector>)时,每次遍历节点 u 都要扫描整行(O(V)),总时间是 O(V²);邻接表只遍历实际边,总时间是 O(V + E)。实际项目中除非图极稠密或节点数

  • vector<vector>></vector> 是主流邻接表,但若频繁删边,可考虑 vector<set>></set>;不过 DFS 不涉及删边,无需过度设计
  • 若图是稀疏的(如社交网络子图),邻接表内存更省,缓存友好性也更好
  • DFS 本身不依赖图存储方式,但写错循环范围(比如把 graph[u].size() 写成 n)会导致越界或漏边
  • 递归太深导致栈溢出?std::stack 非递归版也不是万能解药

    当图节点数超 10⁵ 且深度极大(如链状图),递归 DFS 很容易触发栈溢出;此时非递归版确实能避免函数调用栈问题。但要注意:

    • std::stack 默认用 deque 实现,内存分配较频繁;对超大图,可换用 stack<int vector>></int> 提升连续内存局部性
    • 非递归版仍需 O(V) 空间存 visitedstack,空间复杂度没变,只是把栈空间从系统栈挪到了堆上
    • 若需获取路径、回溯状态(如找连通分量中的割点),单纯非递归 DFS 不够,得补全“当前层数”或“父节点”信息,这时递归结构反而更直观
    真正卡住性能的往往不是递归深度,而是邻接表遍历中反复调用 vector::begin()/end() 或未 reserve 容量——这些细节比选递归/非递归更影响实测表现。

    热门AI工具

    更多
    DeepSeek
    DeepSeek

    幻方量化公司旗下的开源大模型平台

    豆包大模型
    豆包大模型

    字节跳动自主研发的一系列大型语言模型

    通义千问
    通义千问

    阿里巴巴推出的全能AI助手

    腾讯元宝
    腾讯元宝

    腾讯混元平台推出的AI助手

    文心一言
    文心一言

    文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

    讯飞写作
    讯飞写作

    基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

    即梦AI
    即梦AI

    一站式AI创作平台,免费AI图片和视频生成。

    ChatGPT
    ChatGPT

    最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

    相关专题

    更多
    堆和栈的区别
    堆和栈的区别

    堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

    416

    2023.07.18

    堆和栈区别
    堆和栈区别

    堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

    588

    2023.08.10

    堆和栈的区别
    堆和栈的区别

    堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

    416

    2023.07.18

    堆和栈区别
    堆和栈区别

    堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

    588

    2023.08.10

    页面置换算法
    页面置换算法

    页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

    449

    2023.08.14

    pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
    pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

    本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

    77

    2026.02.13

    微博网页版主页入口与登录指南_官方网页端快速访问方法
    微博网页版主页入口与登录指南_官方网页端快速访问方法

    本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

    49

    2026.02.13

    Flutter跨平台开发与状态管理实战
    Flutter跨平台开发与状态管理实战

    本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

    21

    2026.02.13

    TypeScript工程化开发与Vite构建优化实践
    TypeScript工程化开发与Vite构建优化实践

    本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

    10

    2026.02.13

    热门下载

    更多
    网站特效
    /
    网站源码
    /
    网站素材
    /
    前端模板

    精品课程

    更多
    相关推荐
    /
    热门推荐
    /
    最新课程
    C# 教程
    C# 教程

    共94课时 | 9.4万人学习

    C 教程
    C 教程

    共75课时 | 4.7万人学习

    C++教程
    C++教程

    共115课时 | 17.7万人学习

    关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
    php中文网:公益在线php培训,帮助PHP学习者快速成长!
    关注服务号 技术交流群
    PHP中文网订阅号
    每天精选资源文章推送

    Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号