dfs递归栈溢出因未控深度、图大或有环且未标记访问;须用visited数组防无限递归;邻接表优选vector,超大编号用unordered_map;非递归dfs可避栈溢出。

DFS 递归写法为什么栈溢出?
因为没控制递归深度,或者图太大、有环但没标记访问状态。C++ 默认栈空间小,深递归直接崩。
- 必须用
visited数组/集合标记已访问节点,否则无限递归 - 邻接表用
vector<vector>></vector>比vector<list>></list>更快,缓存友好 - 若图节点编号不连续或范围极大(比如 1e9),改用
unordered_map<int vector>></int>存图,但visited也得用unordered_set - 手动模拟栈的 DFS(非递归)能避开栈溢出,但代码稍长:用
stack<int></int>+while循环 + 显式压栈/弹栈
BFS 用 queue 还是 deque?
日常用 queue 就够了;只有需要从队首插入(比如 0-1 BFS)才换 deque。别为“听起来更通用”滥用 deque。
-
queue底层默认是deque,性能无差别;选它语义更清晰 - 别用
vector手搓队列——pop_front()是 O(n),BFS 复杂度直接升到 O(n²) - 如果要记录层数(比如最短路径长度),在每轮
while前用int size = q.size()固定当前层宽度,别边遍历边push边size() - 多源 BFS(如多个起点同时出发)只需初始把所有起点
push进队,逻辑不变
邻接表 vs 邻接矩阵:图稀疏时别硬用二维数组
点数 1e4、边数 1e4 的图,用 vector<vector>></vector> 开 1e4×1e4 内存就爆了(100MB+),而且遍历效率低。
- 稀疏图(边数 ≈ 点数)必用邻接表:
vector<vector>> graph(n)</vector> - 邻接矩阵只适合点数 ≤ 1e3 且需频繁查「u 到 v 是否有边」的场景;查边用
graph[u][v]是 O(1),但初始化和遍历都是 O(n²) - 如果边带权且稀疏,邻接表存
vector<vector int>>></vector>,第二项是权重;别为了省事全用 map 嵌套,常数大 - 无向图加边记得双向:
graph[u].push_back(v)和graph[v].push_back(u)
DFS/BFS 返回值怎么设计才不踩坑?
别让函数既遍历又返回布尔值判断连通性,又塞路径结果——职责混在一起,调试时根本分不清哪步挂了。
立即学习“C++免费学习笔记(深入)”;
- 单纯遍历:函数
void dfs(int u, vector<bool>& visited, const vector<vector>>& graph)</vector></bool>,副作用修改visited - 查连通性:单独写
bool isConnected(int start, int target, ...),内部调用 DFS/BFS,末尾返回visited[target] - 要路径:BFS 天然支持,用
vector<int> parent</int>记前驱,找到终点后倒推;DFS 要回溯,路径存在vector<int> path</int>里,进递归push_back,出递归pop_back - 全局变量(如
path或found)必须重置,尤其写在类里多次调用时,别忘了在入口清空









