商城首页欢迎来到中国正版软件门户

您的位置:首页 >C++实现深度优先搜索(DFS)求路径 _ 邻接表表示与递归【源码】

C++实现深度优先搜索(DFS)求路径 _ 邻接表表示与递归【源码】

  发布于2026-05-03 阅读(0)

扫一扫,手机访问

DFS路径记录的关键是维护path容器并在回溯时及时pop;需用visited数组防环,邻接表推荐vector>,找第一条路径须用引用bool变量found控制提前退出。

C++实现深度优先搜索(DFS)求路径 _ 邻接表表示与递归【源码】

DFS递归实现路径记录的关键在哪

说起来,DFS记录路径的核心,其实就围绕着一个容器和一个动作:维护好那个path容器,并在回溯时及时把节点弹出来。当然,不是所有DFS都需要记录具体路径,但一旦你的需求是输出从A点到B点的完整路线,这个“进栈-出栈”的节奏就至关重要了。忘了弹出节点?那path里就会混杂不同分支的“脚印”,最终得到的路径要么长度诡异,要么根本就不是你想要的。

常见的翻车现场包括:路径里出现了毫不相干的节点;明明存在通路却搜索不到;或者得到的路径长度和预期对不上。

  • 通常推荐用std::vector来存路径,简单直观,下标天然反映了访问顺序。
  • 递归函数签名里,记得把邻接表const std::vector>& graph和当前节点u作为参数传进去,避免不必要的拷贝开销。
  • 终止条件可不能只看u == target,还得加上对visited数组的判断,防止在环里打转。

邻接表怎么建才方便 DFS 遍历

要论轻便高效,std::vector>绝对是首选。直接用节点编号(假设是0到n-1)作为索引,访问起来飞快。除非节点编号极其稀疏且不连续,否则别轻易动用std::map>——它带来的键值查找开销和额外的判空逻辑,在遍历时都是负担。

建表时得留心方向:有向图只加一条边graph[u].push_back(v);如果是无向图,那就得双向添加。另外,如果输入数据习惯从1开始计数,一个好习惯是读入后立刻统一转成0-indexed,这样后续所有数组操作都会安全得多。

立即学习“C++免费学习笔记(深入)”;

  • 初始化时,直接用graph.resize(n)设定大小,比循环里push_back空向量要高效。
  • 切记,遍历过程中别去修改graph的结构,否则很容易打乱整个搜索逻辑。
  • 如果边带权重,那就得升级一下数据结构,比如用std::vector>>,把邻接点和权重打包存放。

如何让 DFS 找到第一条路径就返回

标准的DFS会不辞劳苦地探索所有可能,但在很多实际场景里——比如找个迷宫出口、或者解析任务依赖——我们往往只要任意一条可行路径就足够了。这时候,光靠递归函数里的return可不够,它只能结束当前层的调用,控制不了整个递归栈。正确的做法,是引入一个“哨兵”——一个布尔类型的引用变量found

典型的错误是在找到目标后直接return,结果上层递归还在继续尝试其他分支。而正确的逻辑是,在每一层递归开始都先检查一下if (found) return,一旦找到路径,就立即把found设为true,然后层层返回。

  • 函数签名可以设计成这样:bool dfs(int u, int target, std::vector& path, std::vector& visited, bool& found)
  • 找到目标节点时,先把它压入path,然后设置found = true并返回true
  • 这样,调用方只要检查返回值是否为true,就能立刻拿到路径,无需等待整个递归树遍历完毕。

为什么你的 DFS 总是栈溢出或超时

这个问题背后通常有两个“元凶”:要么是递归深度太大(比如节点数超过10^5),超出了默认栈空间的承受能力;要么就是图里存在环,而visited数组没有正确更新,导致搜索陷入了无限递归。C++的默认栈空间并不大,深度达到1e5量级时,栈溢出几乎是必然的。

  • 首要原则:务必初始化visited数组,并且在访问每个新节点前严格执行if (visited[u]) return
  • 面对大规模图,可以考虑改用手动维护栈的迭代DFS,或者为递归深度设置一个上限。
  • 开启编译优化-O2或许能提升一些性能,但它解决不了算法本身的逻辑缺陷。
  • 调试时有个小技巧:可以临时加一个静态变量来记录深度,比如static int depth = 0; depth++; if (depth > 1000) { /* 输出日志 */ },快速定位是不是递归过深了。

说到底,记录路径的代码本身并不复杂,真正的挑战在于保持递归过程中状态的“洁净”,在各种边界条件下统一控制流程,以及在大规模数据面前守住性能和资源的底线。这些细节如果当时没写清楚,下次维护代码时,很可能还会在同一个地方再摔一跤。

本文转载于:https://www.php.cn/faq/2313722.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注