红黑树删除需维护五大性质,黑色叶子删除触发双黑修复;后继替换含指针重连与颜色继承,单子树节点替换时子节点必为红色,双子树采用右子树最左节点作后继,修复过程分四类情形处理,时间复杂度O(log n)。

在C++中实现红黑树节点删除时,必须同步维护红黑树的五大性质,尤其当被删节点为黑色且子节点均为空时,将触发复杂的双黑修复流程;后继节点替换不是简单值拷贝,而是指针重连与颜色继承的组合操作,稍有不慎就会导致树结构失衡或颜色链断裂。
定位待删除节点并处理基础情况
从根节点开始,按BST规则向下查找目标key值对应的节点;若未找到,直接返回false。
若该节点左、右子树均为空(即叶子节点),则记录其父节点指针和自身在父节点中的左右方位,准备执行物理删除;此时若该节点为红色,直接删掉即可,无需修复——【红色叶子删除不触发任何修复】。
若该节点仅有一侧子树非空,则用其唯一子节点直接顶替其位置,并继承原节点颜色;注意:该子节点必定为红色(因红黑树不允许连续两个红色节点,而原节点若为红色则子节点必黑,但单子树情况下若原节点为黑、子节点为黑会违反黑高一致,故实际只可能子节点为红)。
双子树节点的后继替换策略
方法一:用后继节点(右子树最左节点)替换
进入待删节点的右子树→一直向左走到最底层的左孩子节点,该节点即为后继;若后继节点本身有右子树(它不可能有左子树),则将其右子节点挂到后继父节点的左链上;然后将后继节点的值复制到待删位置,再真正删除后继节点。
方法二:用前驱节点(左子树最右节点)替换
进入待删节点的左子树→一直向右走到最底层的右孩子节点,该节点即为前驱;若前驱节点有左子树,将其左子节点接续到前驱父节点的右链;完成值拷贝后,物理删除前驱节点。
两种方法等价,但实践中多采用后继,因标准库STL set/map内部也使用右子树最小值作为替换点;【必须确保后继节点至多只有一个子节点,否则无法安全摘除】。
删除黑色叶子引发的双黑修复流程
第一步:将被删位置标记为“双黑”(double-black),即该空位需承担两个黑色计数才能满足黑高平衡;
第二步:根据双黑节点的兄弟节点颜色与结构分四类处理:
① 兄弟为红色 → 先对父节点做一次旋转使兄弟变黑、父变红,再进入兄弟为黑的后续情形;
② 兄弟为黑色,且其两个子节点均为黑色 → 将兄弟染红,父节点变为新的双黑节点,向上递归修复;
③ 兄弟为黑色,近侄(靠近双黑一侧的子节点)为红、远侄为黑 → 对兄弟做一次反向旋转,交换近侄与兄弟颜色,转为情形④;
④ 兄弟为黑色,远侄为红 → 将兄弟染成父节点颜色,父与远侄染黑,围绕父节点做一次旋转,修复结束。
整个修复过程不新增节点也不改变原有键值顺序,仅通过颜色翻转与局部旋转维持红黑性质;每轮最多执行两次旋转,时间复杂度O(log n)。
关键指针重连与颜色继承实现细节
当以后继节点s替换原节点z时,先保存s的原始颜色color_s;将s的右子节点r设为s父节点的左子(若s是其父的右孩子)或右子(若s是其父的左孩子);然后将z的父节点、左子、右子全部赋给s;最后将s的颜色设为z的原始颜色。
特别注意:若s原本就是z的右孩子,则s->right就是z->right,此时不能把z->right再赋给s->right,否则形成自环;应先断开s与其父的连接,再拼接z的左右子树到s上。
这一步操作起来很简单,直接修改指针域即可,但必须严格按父子关系拓扑顺序执行,错序会导致内存泄漏或野指针。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











