正确做法是定义 class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val; self.left = left; self.right = right,显式初始化左右子节点为 None,避免 AttributeError。

怎么定义 Python 二叉树节点才不踩坑
直接用 class TreeNode 定义就行,但很多人漏掉 val 的默认值或子节点初始化,导致后续递归时出现 AttributeError: 'NoneType' object has no attribute 'left'。
正确做法是显式初始化左右子节点为 None,避免依赖调用方传参补全:
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right-
val=0防止建节点时不传值报错(比如只写TreeNode()) -
left=None和right=None是关键:递归遍历时会直接访问node.left,若没初始化,就是AttributeError - 别用字典或命名元组模拟节点——看起来省事,但类型模糊、IDE 提示弱、递归调试时难追踪
前序/中序/后序递归遍历的统一写法
三者结构完全一致,只差一行语句顺序。硬背顺序容易混淆,不如记住「根的位置决定名字」:前序=根在前,中序=根在中,后序=根在后。
实操建议统一用「空节点返回」+「非空节点按序操作」模式,避免分支嵌套过深:
立即学习“Python免费学习笔记(深入)”;
# 前序:根 → 左 → 右
def preorder(root):
if not root:
return []
return [root.val] + preorder(root.left) + preorder(root.right)
<h1>中序:左 → 根 → 右</h1><p>def inorder(root):
if not root:
return []
return inorder(root.left) + [root.val] + inorder(root.right)</p><h1>后序:左 → 右 → 根</h1><p>def postorder(root):
if not root:
return []
return postorder(root.left) + postorder(root.right) + [root.val]- 所有函数都以
if not root:开头,这是递归终止条件,不能省;漏了就无限递归 - 返回值拼接用
+看起来直观,但注意:每次调用都会新建列表,空间开销大;生产环境建议改用传入res列表引用的方式 - 别把
print(root.val)当作遍历——它不收集结果,无法用于后续处理(比如判断是否对称、找第 k 小)
为什么递归遍历时总遇到栈溢出或结果为空
不是代码逻辑错,大概率是输入本身有问题:空树、节点链式退化、或误把列表当树传入。
常见错误现象和对应检查点:
- 函数返回空列表
[]:先确认root是否为None,再检查构造树时有没有把left/right写成字符串或数字(比如TreeNode(1, 2, 3)—— 这里 2 和 3 不是节点,是 int) -
RecursionError: maximum recursion depth exceeded:说明树深度太大(比如单链状树有上万层),Python 默认递归限制约 1000 层;此时必须改迭代,或手动设sys.setrecursionlimit()(不推荐) - 结果顺序对不上:检查你用的是哪类遍历,再核对树结构——手画三节点树(根+左+右),代入函数一步步推,比看代码更快定位错在哪一层
构建测试用二叉树的快捷方式
手写 TreeNode(1, TreeNode(2), TreeNode(3)) 太慢,又容易括号错位。用层级数组转树是最稳的快速构建法,尤其适合 LeetCode 风格输入(如 [3,9,20,null,null,15,7])。
核心思路:数组索引 i 的左右子节点在 2*i+1 和 2*i+2,用队列逐层连接:
def build_tree(nums):
if not nums or nums[0] is None:
return None
root = TreeNode(nums[0])
q = [root]
i = 1
while q and i < len(nums):
node = q.pop(0)
if i < len(nums) and nums[i] is not None:
node.left = TreeNode(nums[i])
q.append(node.left)
i += 1
if i < len(nums) and nums[i] is not None:
node.right = TreeNode(nums[i])
q.append(node.right)
i += 1
return root- 输入
[1,2,3,None,4]会生成正确结构;None必须用 Python 的None,不能用字符串"null"或数字0 - 这个函数不校验数组是否合法(比如中间缺太多
None),但够日常调试用;真要健壮,得加索引越界保护 - 别依赖 IDE 可视化插件看树形——它们常把
None子节点也展开,干扰判断;打印inorder(build_tree([1,2,3]))看输出最可靠
树的递归本质就两点:明确终止条件、保证每层只做一件事。难点不在语法,而在构造输入时一个 None 没写对,或者遍历时把 root.left 错当成 root.left.val —— 这些细节卡住的时间,往往比写逻辑还长。


















