BST插入必须先判空根节点,否则空指针崩溃;递归需用返回值更新父节点指针;迭代需显式维护父指针并正确挂载;重复值策略须统一明确。

插入节点前必须判断根是否为空
二叉搜索树(BST)插入的起点永远是根节点,如果 root 为 nullptr,直接新建节点并返回,跳过所有比较逻辑。这一步漏掉会导致空指针解引用崩溃,尤其在递归实现中容易忽略初始边界。
- 非递归插入需在循环前单独检查
root == nullptr - 递归插入的 base case 必须是
if (root == nullptr) return new TreeNode(val); - 若用引用传参(如
TreeNode*& root),赋值后无需 return,但首次调用仍需确保传入的是可修改的左/右指针
递归插入时注意返回值与指针更新
递归版本不能只“调用”子树插入,必须用返回值重新链接父节点的左右指针,否则新节点无法挂载到树上。常见错误是写了 insertIntoBST(root->left, val) 却没写 root->left = insertIntoBST(root->left, val)。
TreeNode* insertIntoBST(TreeNode* root, int val) {
if (root == nullptr) {
return new TreeNode(val);
}
if (val < root->val) {
root->left = insertIntoBST(root->left, val); // ← 关键:必须赋值
} else {
root->right = insertIntoBST(root->right, val); // ← 同样必须赋值
}
return root;
}非递归插入要手动维护父节点指针
迭代写法没有函数调用栈帮你记住“上一个节点”,必须显式保存 parent,并在跳出循环后根据比较结果把新节点挂到 parent->left 或 parent->right。否则新节点会丢失。
- 循环中只移动
current,不更新parent→ 永远找不到挂载点 - 忘记在循环外判断
parent == nullptr(即原树为空)→ 插入失败 - 比较逻辑写反(比如
val val)→ 破坏 BST 性质(重复值处理需明确策略)
重复值插入需明确定义行为
C++ 标准 BST 实现通常不允许多个相同值,但题目未说明时,必须确认需求:是忽略、插入右子树、还是插入左子树?LeetCode 701 默认允许重复插入右子树,但实际工程中更常见的是拒绝重复或使用 std::multiset。
立即学习“C++免费学习笔记(深入)”;
- 若忽略重复:在递归或迭代入口加
if (val == root->val) return root; - 若插入右子树:用
val val则左,否则右 → 但会导致右子树含等值,破坏严格 BST 定义 - 真正合规的做法是文档化行为,并在所有插入路径统一处理,避免一部分忽略、一部分插入
BST 构建看似简单,真正容易出问题的地方不在算法逻辑,而在指针链接时机、空节点处理和重复值约定——这三个点任意一个没对齐,整棵树就会不可靠。











