void RBTREE_REMOVE_NODE(struct RBTREE_TYPENAME* target, struct RBTREE_NODE* N) { DEBUG_RBTREE("rbtree_remove_node: "RBTREE_KEY_PRNF"\n", RBTREE_KEY_PRNA(N->key)); valgrind_assert(target->size >= 1); DEBUG_RBTREE("before:\n"); // RBTREE_PRINT(target); if (target->size == 1) { valgrind_assert(target->root == N); target->root = 0; goto end; } // If N has two children, we use replacement R: in-order successor { struct RBTREE_NODE* R = NULL; if (N->right != NULL && N->left != NULL) R = rbtree_leftmost_loop(N->right); if (R != NULL) swap_nodes(target, N, R); delete_one_child(target, N); DEBUG_RBTREE("after:\n"); // RBTREE_PRINT(target); } end: target->size--; }
void rb_delete(rb_node* n, rb_tree* tree) { #ifdef DEBUG if(!is_leaf(n->left, tree)) assert(is_leaf(n->right, tree)); if(!is_leaf(n->right, tree)) assert(is_leaf(n->left, tree)); #endif delete_one_child(n, tree); tree->n--; }
void delete_one_child(ptr_rbnode node) { ptr_rbnode s = get_sibiling(node), p = node->parent; if (p) { if (s->color == RED) { p->color = RED; s->color = BLACK; if (p->left == node) { rotate_left(p); } else { rotate_right(p); } } s = get_sibiling(node), p = node->parent; if (s->color == BLACK && s->left->color == BLACK && s->right->color == BLACK) { if (p->color == BLACK) { s->color = RED; delete_one_child(p); } else { s->color = RED; p->color = BLACK; } } else { if (node->parent->left == node && s->right->color == RED) { s->color = p->color; p->color = BLACK; s->right->color = BLACK; rotate_left(p); } else if (node->parent->left == node && s->left->color == RED) { s->left->color = p->color; p->color = BLACK; rotate_right(s); rotate_left(s->parent->parent); } else if (node->parent->right == node && s->left->color == RED) { s->color = p->color; p->color = BLACK; s->left->color = BLACK; rotate_right(p); } else if (node->parent->right == node && s->right->color == RED) { s->right->color = p->color; p->color = BLACK; rotate_left(s); rotate_right(s->parent->parent); } else assert(0 && "balance error"); } } }
ptr_rbnode delete_node(ptr_rbnode root, rbtree_element_type_t val, int logging) { ptr_rbnode node = find_node(root, val); if (node) { ptr_rbnode left_max_node = NULL; if (node->left->nil == 0 && node->right->nil == 0) { left_max_node = find_max_node(node->left); node->val = left_max_node->val; node = left_max_node; } ptr_rbnode child = node->right->nil == 1 ? node->left : node->right; if (node->color == BLACK) { node->color = child->color; delete_one_child(node); } root = replace_node(root, child, node); free(node); return root; } else { if (logging) printf("%d is not in the tree\n", val); return root; } }