紅黑樹作為自平衡二叉搜尋樹,維持以下五大性質:
刪除操作時間複雜度同為 O(log₂N),但處理邏輯較插入複雜。
假設需刪除節點 D,分三種情況處理:
用右子節點取代 D 的位置。若 D 為紅色,性質未破壞;若 D 為黑色,需進一步調整。
用左子節點取代 D 的位置。同樣,D 為紅色無需調整,黑色則需調整。
找到 D 的後繼節點 S,將 S 的 key 值賦給 D,再刪除 S 並用 S 的右子節點取代 S 位置。實際被刪除的是 S。若 S 為紅色無需調整,黑色則需調整。
結論:僅當實際被刪除的節點為黑色時,才可能破壞紅黑樹性質,需進入調整階段。
將 P 改紅、B 改黑,以 P 為支點左旋 → 轉化為案例 2、3 或 4。
將 B 改紅 → 調整結束,重新判斷前提條件。
B 改紅、B 左子改黑,以 B 為支點右旋 → 必轉化為案例 4 繼續處理。
將 P 顏色複製給 B,P 改黑、B 右子改黑,以 P 為支點左旋,將參照節點設為根 → 調整結束。
前提 2(N 為 P 的右子節點)處理流程對稱,此處略過。
rbt_deleteint rbt_delete(rbt_tree_t *tree, int key) {
rbt_node_t *node = tree->root;
if (tree->sentinel == node) return RBT_SUCCESS;
while (tree->sentinel != node) {
if (key == node->key) return _rb_delete(tree, node);
else if (key < node->key) node = node->lchild;
else node = node->rchild;
}
return RBT_SUCCESS;
}
_rb_deleteint _rb_delete(rbt_tree_t *tree, rbt_node_t *dnode) {
rbt_node_t *parent = NULL, *next = NULL, *refer = NULL;
// 尋找後繼節點 next
if ((tree->sentinel == dnode->lchild) || (tree->sentinel == dnode->rchild))
next = dnode;
else {
next = dnode->rchild;
while (tree->sentinel != next->lchild) next = next->lchild;
}
// 設置替代節點 refer
refer = (tree->sentinel != next->lchild) ? next->lchild : next->rchild;
refer->parent = next->parent;
// 更新父節點連結
if (tree->sentinel == next->parent) tree->root = refer;
else if (next == next->parent->lchild) next->parent->lchild = refer;
else next->parent->rchild = refer;
// 若刪除的是後繼節點,複製資料
if (next != dnode) dnode->key = next->key;
// 紅色節點直接釋放,黑色需修復
if (rbt_is_red(next)) { free(next); return RBT_SUCCESS; }
free(next);
return rbt_delete_fixup(tree, refer);
}
rbt_delete_fixupint rbt_delete_fixup(rbt_tree_t *tree, rbt_node_t *node) {
rbt_node_t *parent = NULL, *brother = NULL;
while (rbt_is_black(node) && (tree->root != node)) {
parent = node->parent;
if (node == parent->lchild) {
brother = parent->rchild;
// Case 1: 兄弟紅
if (rbt_is_red(brother)) {
rbt_set_red(parent); rbt_set_black(brother);
rbt_left_rotate(tree, parent);
brother = parent->rchild;
}
// Case 2: 兄弟黑且雙子皆黑
if (rbt_is_black(brother->lchild) && rbt_is_black(brother->rchild)) {
rbt_set_red(brother); node = parent;
} else {
// Case 3: 兄弟黑、左紅右黑
if (rbt_is_black(brother->rchild)) {
rbt_set_black(brother->lchild); rbt_set_red(brother);
rbt_right_rotate(tree, brother);
brother = parent->rchild;
}
// Case 4: 兄弟黑、右紅
rbt_copy_color(brother, parent);
rbt_set_black(brother->rchild); rbt_set_black(parent);
rbt_left_rotate(tree, parent);
node = tree->root;
}
} else { /* 對稱處理右子節點情況 */ }
}
rbt_set_black(node);
return RBT_SUCCESS;
}

隨機生成樹並刪除隨機節點後,結果仍滿足紅黑樹性質,經反覆驗證代碼正確。