/*rbtree_delete*/ void mln_sarbt_delete(mln_sarbt_t *t, mln_sarbt_node_t *n) { enum sarbt_color y_original_color; mln_sarbt_node_t *x, *y; y = n; y_original_color = y->color; if (n->left == &(t->nil)) { x = n->right; rbtree_transplant(t, n, n->right); } else if (n->right == &(t->nil)) { x = n->left; rbtree_transplant(t, n, n->left); } else { y = rbtree_minimum(t, n->right); y_original_color = y->color; x = y->right; if (y->parent == n) x->parent = y; else { rbtree_transplant(t, y, y->right); y->right = n->right; y->right->parent = y; } rbtree_transplant(t, n, y); y->left = n->left; y->left->parent = y; y->color = n->color; } if (y_original_color == M_SARB_BLACK) rbtree_delete_fixup(t, x); n->parent = n->left = n->right = &(t->nil); }
void util_rbtree_delete(util_rbtree_t *rbtree, util_rbtree_node_t *node) { int isblack; util_rbtree_node_t *temp, *subst; if((rbtree==NULL) || (node==NULL) || (node==_NULL(rbtree))) { return; } rbtree->size--; /* find deleted position, indicated by temp */ if(node->left == _NULL(rbtree)) { temp = node; subst = node->right; } else if(node->right == _NULL(rbtree)) { temp = node; subst = node->left; } else /* right & left aren't null */ { temp = util_rbsubtree_min(node->right, _NULL(rbtree)); if(temp->left != _NULL(rbtree)) { subst = temp->left; } else { subst = temp->right; } } if(temp == rbtree->root) /* temp is root */ { rbtree->root = subst; util_rbt_black(subst); rbt_clear_node(temp); return; } isblack = util_rbt_isblack(temp); /* temp will be removed from it's position, rebuild links * NOTE: if temp->parent = node, then subst->parent is node * while node is the one to be delete, so relink subst's parent to temp * because temp will replace node's in the tree */ if(temp->parent == node) { subst->parent = temp; } else { subst->parent = temp->parent; } if(temp == temp->parent->left) { temp->parent->left = subst; } else { temp->parent->right = subst; } /* * now temp is removed from the tree. * so we will make temp to replace node in the tree. */ if(temp != node) { temp->parent = node->parent; if(node == rbtree->root) /* node maybe root */ { rbtree->root = temp; } else { if(node->parent->left == node) { node->parent->left = temp; } else { node->parent->right = temp; } } temp->right = node->right; temp->left = node->left; if(temp->left != _NULL(rbtree)) { temp->left->parent = temp; } if(temp->right != _NULL(rbtree)) { temp->right->parent = temp; } temp->color = node->color; } rbt_clear_node(node); if(isblack) { /* temp is black, fix up delete */ rbtree_delete_fixup(rbtree, subst); } }
/* * 删除结点 * * 参数说明: * tree 红黑树的根结点 * node 删除的结点 */ void rbtree_delete(RBRoot *root, Node *node) { Node *child, *parent; int color; // tree // / \ // dnode // / \ // left right // / \ // replace right // 被删除节点的"左右孩子都不为空"的情况。 if ( (node->left!=NULL) && (node->right!=NULL) ) { // 被删节点的后继节点。(称为"取代节点") // 用它来取代"被删节点"的位置,然后再将"被删节点"去掉。 Node *replace = node; // 获取后继节点 replace = replace->right; while (replace->left != NULL) replace = replace->left; // "node节点"不是根节点(只有根节点不存在父节点) if (rb_parent(node)) { if (rb_parent(node)->left == node) rb_parent(node)->left = replace; else rb_parent(node)->right = replace; } else // "node节点"是根节点,更新根节点。 root->node = replace; // child是"取代节点"的右孩子,也是需要"调整的节点"。 // "取代节点"肯定不存在左孩子!因为它是一个后继节点。 child = replace->right; parent = rb_parent(replace); // 保存"取代节点"的颜色 color = rb_color(replace); // "被删除节点"是"它的后继节点的父节点" if (parent == node) { parent = replace; } else { // child不为空 if (child) rb_set_parent(child, parent); parent->left = child; replace->right = node->right; rb_set_parent(node->right, replace); } replace->parent = node->parent; replace->color = node->color; replace->left = node->left; node->left->parent = replace; if (color == BLACK) rbtree_delete_fixup(root, child, parent); free(node); return ; } if (node->left !=NULL) child = node->left; else child = node->right; parent = node->parent; // 保存"取代节点"的颜色 color = node->color; if (child) child->parent = parent; // "node节点"不是根节点 if (parent) { if (parent->left == node) parent->left = child; else parent->right = child; } else root->node = child; if (color == BLACK) rbtree_delete_fixup(root, child, parent); free(node); }