生成器实现回溯路径搜索的核心是利用yield暂停/恢复执行上下文隐式保存状态,无需显式栈;每步需配对path.append()与path.pop()手动撤销,yield path.copy()输出解。

用生成器实现带回溯功能的路径搜索迭代,核心是把“每一步的选择—验证—进入—退回”过程封装成可暂停、可恢复的迭代逻辑,而不是靠显式栈或递归调用栈。它不维护完整状态栈,而是靠生成器函数的执行上下文(即 yield 暂停点)天然保存局部变量和控制流位置,从而隐式实现回溯行为。
生成器回溯的本质:用 yield 暂停代替 return 回退
传统递归回溯靠函数调用栈保存每层的候选索引、已选路径、约束状态;而生成器每次 yield 后挂起自身,下次 next() 或 for 循环继续时,自动恢复全部局部变量(如当前坐标、已走路径、访问标记),无需手动压栈/弹栈。这使代码更简洁,且内存开销可控。
- 每次
yield path.copy()输出一个完整可行路径,不修改原路径对象 - 路径扩展用
path.append(),回溯用path.pop()——这是显式撤销操作,与生成器挂起无关,但必须配对出现 - 生成器函数本身不返回值,只通过
yield逐个产出解,调用方按需消费
二维网格路径搜索的生成器写法
以无障碍网格中从 (0,0) 到 (m-1,n-1) 的所有路径为例(只允许右、下移动):
(Python 示例)
def path_generator(grid, start=(0, 0), end=None):
if end is None:
end = (len(grid) - 1, len(grid[0]) - 1)
m, n = len(grid), len(grid[0])
path = [start]
<pre class="brush:php;toolbar:false;">def dfs(x, y):
if (x, y) == end:
yield path.copy() # 找到一条路径,产出
return
# 尝试向右
if y + 1 < n and grid[x][y + 1] == 0:
path.append((x, y + 1))
yield from dfs(x, y + 1)
path.pop()
# 尝试向下
if x + 1 < m and grid[x + 1][y] == 0:
path.append((x + 1, y))
yield from dfs(x + 1, y)
path.pop()
yield from dfs(*start)
-
yield from将子生成器的产出委托给外层,保持迭代链路畅通 - 每个
path.append()后必须紧跟path.pop(),否则路径会持续累积——这是手动“撤销”,不可省略 - 障碍判断(
grid[x][y] == 0)和越界检查放在分支入口,避免无效递归
支持剪枝与限界的生成器增强版
当需要找“最优路径”(如步数最少、金币最多)时,可在生成器中传入当前代价,并在 yield 前判断是否优于已有最优值:
- 把
best_cost作为参数传入或用 nonlocal 变量跟踪 - 每次到达终点时,比较当前 cost 与 best_cost,仅当更优才
yield - 若当前 cost 已超过 best_cost(如求最小步数但已走 > 最优步数),直接 return,跳过后续分支——这就是限界剪枝
例如在迷宫中收集金币,用 current_gold 累计,遇到死路或金币上限已超时提前退出,比纯 DFS 更高效。
与显式迭代栈方式的关键区别
生成器方案不是“模拟栈”,而是利用语言运行时机制隐式保存控制流。它不需定义 (depth, candidates, next_index, state) 这类元组结构,也不用手动管理栈的 push/pop 时机。
- 优点:逻辑贴近自然递归思维,易读易调试;无栈溢出风险(深度大时仍稳定)
- 缺点:无法中途修改搜索策略(如动态调整候选顺序);难以精确控制内存驻留对象(path 列表反复 copy)
- 适用场景:解空间适中、路径结构清晰、强调代码可维护性而非极致性能的路径枚举任务

















