最不容易出错的inorderTraversal递归实现是:显式初始化TreeNode指针为nullptr,传TreeNode参数并判空,结果存入vector<int>&引用;非递归版需用stack<TreeNode>,先向左压栈到底,再逐个弹出访问并压入右子树。

怎么写一个能跑通的 inorderTraversal 函数
递归实现最不容易出错,但得确保节点结构定义清晰、空指针检查到位。C++ 里常见错误是忘记判 nullptr 就直接访问 left 或 right,一跑就崩。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 节点结构必须显式初始化指针:
TreeNode* left = nullptr;,别依赖默认值 - 递归函数参数别传值(比如
TreeNode root),必须传指针或引用:void inorder(TreeNode* node) - 遍历结果存进
std::vector<int>&引用里,避免反复拷贝
void inorder(TreeNode* node, vector<int>& res) {
if (!node) return;
inorder(node->left, res);
res.push_back(node->val);
inorder(node->right, res);
}非递归版 inorderTraversal 为什么总卡在空栈或死循环
核心问题是:入栈和出栈时机没对齐,尤其处理完左子树后,不知道该转向右子树还是回退父节点。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 用
stack<TreeNode*>存待处理节点,别存值 - 外层
while判栈非空,内层while一路向左压栈到底,不访问值 - 每次从栈弹出一个节点,访问它,再把它的
right压栈(如果非空) - 漏掉
right == nullptr的判断,会导致空指针解引用
TreeNode 结构体怎么定义才不踩内存坑
LeetCode 风格的 TreeNode 在本地编译时容易因构造函数缺失或成员未初始化导致未定义行为。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 显式写默认构造函数:
TreeNode() : val(0), left(nullptr), right(nullptr) {} - 带参构造函数加
explicit防隐式转换:explicit TreeNode(int x) : val(x), left(nullptr), right(nullptr) {} - 别用
malloc或裸new后不初始化指针成员;统一用new TreeNode(x) - 测试时手动释放内存?先别急——练习阶段用智能指针太重,但至少别重复
delete同一地址
用 std::queue 做层序遍历时,size() 为什么不能放循环条件里
因为 queue.size() 是实时变化的,放在 for (int i = 0; i < q.size(); ++i) 里会导致循环次数动态缩水,漏掉节点。
实操建议:
立即学习“C++免费学习笔记(深入)”;
- 进循环前先存快照:
int levelSize = q.size(); - 每轮只处理
levelSize个节点,保证一层一清 - 插入子节点时只插非空指针:
if (node->left) q.push(node->left); - 别在循环里调
q.pop()后还用被 pop 掉的指针——必须先取front(),再pop()
复杂点在于:树操作本身不难,难的是 C++ 里每个指针、每次 new/delete、每个容器边界,都得自己盯住。稍一松懈,segmentation fault 或 use-after-free 就来了。











