应将易爆栈的递归(如树遍历、深JSON解析、最坏快排、未剪枝回溯)转为显式栈迭代,核心是用栈模拟调用帧状态,如(node, state),避免盲目调高recursion limit。

Python递归太深触发RecursionError: maximum recursion depth exceeded怎么办
直接改:调高sys.setrecursionlimit()不是正解,只是掩盖问题。真正该做的是识别哪些递归本就不该递归——比如树的深度遍历、图的DFS、表达式求值等场景,天然适合转成显式栈迭代。
哪些递归函数最容易踩RecursionError坑
不是所有递归都危险,但以下几类在数据稍大时几乎必爆:
-
os.walk()自定义深层目录遍历时,用递归遍历子目录(尤其遇到符号链接环或超深嵌套) - 解析嵌套过深的JSON或XML(比如>1000层嵌套对象)
- 用递归实现的快速排序/归并排序,最坏情况下递归深度达
O(n)(而非平均的O(log n)) - 未经剪枝的回溯算法(如N皇后、数独求解),路径分支多且深
用list模拟栈,把递归转成迭代的关键三步
核心是把“函数调用帧”拆成数据结构存进栈里。以二叉树中序遍历为例:
def inorder_recursive(root):
if not root:
return
inorder_recursive(root.left) # ← 这行压栈逻辑,要手动实现
print(root.val)
inorder_recursive(root.right)改成迭代后,关键不是“去掉递归”,而是明确维护三个信息:当前节点、是否已处理左子树、是否已处理自身。常用模式:
立即学习“Python免费学习笔记(深入)”;
- 栈元素用
tuple或dict,例如(node, state),其中state标记'visit_left'/'visit_self'/'visit_right' - 初始只推入
(root, 'visit_left'),每次从栈顶取一个,按state决定下一步动作并可能再次入栈 - 避免重复入栈:比如左子树已遍历完,就不再推
node.left,而是推(node, 'visit_self')
用collections.deque还是list做栈?性能和可读性怎么权衡
list的.append()和.pop()是O(1)均摊复杂度,日常够用;deque在极端大量操作时略快,但可读性差——尤其当栈里存的是复合状态时,list更直观。
真正要注意的是别误用.insert(0, x)或.pop(0)模拟栈(那是O(n)),也别在循环中反复list.extend()大量元素导致内存抖动。简单场景直接用stack = [],加个注释说明用途即可。
递归转迭代最难的不是语法,是把隐式控制流(调用/返回顺序)显式写成状态机。一旦漏掉某个状态分支,结果就错得悄无声息——比RecursionError更难调试。


















