不能直接用左子节点替代被删节点,因为左子节点不一定是左子树最大值,无法保证bst性质;正确做法是用左子树最右节点(中序前驱)或右子树最左节点(中序后继)替换,并递归删除该前驱/后继节点。

删除节点时,为什么不能直接用左子树根替代被删节点
因为左子树最大值(即中序前驱)才满足 BST 性质:它小于被删节点,又大于左子树其余所有节点。若直接拿 left 子节点顶上,会丢失左子树中比 left 大、但比原节点小的那些节点(比如 left 有右子树时)。正确做法是找左子树的最右节点(findMax(node->left)),它才是安全的替换者。
三种删除场景对应的具体替换逻辑
被删节点 node 的度(子节点数)决定处理路径:
- 度为 0(叶子):直接
delete node,父指针置nullptr - 度为 1:用唯一非空子树(
node->left或node->right)接替其位置,注意更新父节点指向 - 度为 2:必须用中序前驱(左子树最大)或中序后继(右子树最小)替换。选前者时,需先递归删除该前驱节点,再将其值复制到
node;不能只交换指针,否则破坏子树结构
递归删除中,如何安全获取并移除中序前驱
关键在「先摘后填」:不是把前驱节点对象整个搬过来,而是取它的 val 覆盖被删节点,再单独调用 remove 删除前驱本身。这样避免指针混乱。示例片段:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
int maxVal = findMax(node->left)->val; node->val = maxVal; node->left = remove(node->left, maxVal); // 注意:这里传的是 left 子树和 maxVal,不是原 node
漏掉最后这步 node->left = ... 就会导致前驱节点残留,造成重复值或内存泄漏。
迭代实现删除时,为什么推荐用后继而非前驱
右子树的最左节点(中序后继)更容易在迭代中定位:只需不断走 current = current->left,无需回溯父节点。而找左子树最右节点需向右到底,但迭代中一旦进入右分支,就失去对父级 left 指针的控制,容易写错连接逻辑。实际工程中,统一用后继可减少边界判断分支。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










