解析:深度优先搜索、广度优先搜索和回溯搜索
一、深度优先搜索(DFS)
1. 原理
-
思想:从起始节点出发,顺着一条路径不断深入,直到到达目标或无路可走,然后回溯到最近的分支点,继续探索其他分支。
-
应用场景:路径查找、连通性检测、拓扑排序、强连通分量、迷宫求解等。
2. 算法步骤(递归/栈式示例)
DFS(u):标记 u 为已访问for 每个邻居 v ∈ Adj[u]:if v 未访问:DFS(v)
-
伪代码(使用显式栈):
function DFS(start):stack ← 空栈push start 到 stackwhile stack 非空:u ← pop stackif u 未访问:标记 u 为已访问for v ∈ Adj[u]: // 可按任意顺序if v 未访问:push v 到 stack
3. 时间复杂度推导
-
节点个数:|V|
-
边数:|E|
-
每个节点只标记一次,每条边在遍历邻接表时也只会被看一遍(无向图会重复两次,但常写为 O(E))。
-
总时间:
4. 空间复杂度
-
递归栈/显式栈最坏深度为 O(h),h 为搜索深度(在图上为 O(|V|)),加上标记数组 O(|V|)。
-
空间:O(|V| + h) ≈ O(|V|)。
5. 优缺点
-
优点
-
实现简单,递归写法直观。
-
空间开销通常较 BFS 小(受限于深度而非宽度)。
-
易于回溯,可用于拓扑排序、强连通分量等高级图算法。
-
-
缺点
-
不保证最短路径(先深入,再回退)。
-
在最坏情况下可能退入极深的递归,导致栈溢出。
-
对于特别深或含环的图,需要事先做好“已访问”标记防止死循环。
-
二、广度优先搜索(BFS)
1. 原理
-
思想:以起始节点为根,先访问其所有邻居,再依次访问下一层邻居,保证层级(距离)依次递增。
-
应用场景:最短路径(无权图)、分层遍历、最小跳数问题、连通分量检测等。
2. 算法步骤(队列式)
function BFS(start):创建空队列 Q标记 start 为已访问;enqueue start 到 Qwhile Q 非空:u ← dequeue Qfor v ∈ Adj[u]: if v 未访问:标记 v 为已访问enqueue v 到 Q
3. 时间复杂度推导
-
与 DFS 一样,每个顶点进队出队各一次,访问每条边一次。
-
总时间:
4. 空间复杂度
-
队列在最宽层级可能存放 O(w) 个节点,w 最坏可至 O(|V|)。
-
标记数组 O(|V|)。
-
空间:O(|V|)。
5. 优缺点
-
优点
-
保证找到从起点到任一节点的最短(最少边)路径。
-
实现简单,易于理解。
-
-
缺点
-
对内存要求高,最宽层可能存放大量节点。
-
在极度稠密或高 branching 的情况下,空间迅速膨胀。
-
三、回溯搜索(Backtracking)
1. 原理
-
思想:系统地构造解空间树,试探每一个可能的解分支,一旦发现某一路径不可能通向可行解(违反约束或已达死胡同),便“回溯”撤销最近那一步,尝试其他可能。
-
应用场景:组合优化(八皇后、子集和、图着色)、约束满足问题(CSP)、数独、排列生成等。
2. 算法步骤(示例:N 皇后)
function backtrack(状态 state):if state 满足完整解条件:输出一个解returnfor 每个候选分支 choice in 可行 choices(state):做出 choice(更新 state)backtrack(state)撤销 choice(恢复 state)
-
关键在于保持“可行性检测”函数,及时剪枝。
3. 时间复杂度推导
-
记号:
-
b = 平均分支因子(每一步可做的选择数)
-
d = 解的最大深度(决策步数)
-
-
解空间大小:
若无剪枝,则节点总数 ≈ -
因此,最坏时间复杂度:
-
剪枝:若能有效剪枝,平均复杂度可大幅降低,但仍指数级别。
4. 空间复杂度
-
主花销在于递归栈深度 O(d) 及维护当前解的空间 O(d)。
-
空间:O(d)。
5. 优缺点
-
优点
-
通用性强,可处理任意约束问题。
-
通过剪枝和启发式(如最小剩余值、动态变量排序)可极大加速。
-
-
缺点
-
指数级复杂度,极易爆炸。
-
过度依赖剪枝策略和问题结构。
-
四、算法横向对比
特性 | DFS | BFS | Backtracking |
---|---|---|---|
搜索方式 | 深度优先 | 广度优先 | 构造—试探—回溯 |
数据结构 | 递归栈 / 显式栈 | 队列 | 递归栈 |
时间复杂度 | | ||
空间复杂度 | O(V) | O(V) | O(d) |
最短路径 | 不保证 | 保证(无权图) | 视问题而定 |
完整性 | 可遍历整个连通分量 | 可遍历所有可达节点 | 完备(会枚举所有解/证明无解) |
剪枝能力 | 仅防环 | 仅防环 | 高度依赖剪枝策略 |
应用场景 | 拓扑排序、强连通分量等 | 最短路径、层次遍历 | 组合优化、约束满足 |
优点 | 简单,内存小 | 最短路径保证,简单 | 通用性强,可剪枝 |
缺点 | 可能深度过大,易爆栈 | 空间开销大 | 指数爆炸,剪枝难设计 |
-
若关心最短路径:选 BFS;
-
若场景需遍历全图/做结构化分析:可优先 DFS;
-
若需在剪枝约束下寻找可行解或全部解:回溯算法是首选。