static void rbtree_remove_fixup(rbtree_t *tree, rbtree_node_t *node) { rbtree_node_t *brother; while (node != tree->root && rbtree_is_black(node)) { if (node == node->parent->left) { brother = node->parent->right; if (rbtree_is_red(brother)) { rbtree_color_swap(node->parent, brother); rbtree_left_rotate(tree, node->parent); brother = node->parent->right; } if (rbtree_is_black(brother->left) && rbtree_is_black(brother->right)) { rbtree_set_red(brother); node = node->parent; } else { if (rbtree_is_black(brother->right)) { rbtree_color_swap(brother, brother->left); rbtree_right_rotate(tree, brother); brother = node->parent->right; } rbtree_set_black(brother->right); rbtree_color_swap(node->parent, brother); rbtree_left_rotate(tree, node->parent); node = tree->root; } } else { brother = node->parent->left; if (rbtree_is_red(brother)) { rbtree_color_swap(node->parent, brother); rbtree_right_rotate(tree, node->parent); brother = node->parent->left; } if (rbtree_is_black(brother->left) && rbtree_is_black(brother->right)) { rbtree_set_red(brother); node = node->parent; } else { if (rbtree_is_black(brother->left)) { rbtree_color_swap(brother, brother->right); rbtree_left_rotate(tree, brother); brother = node->parent->left; } rbtree_set_black(brother->left); rbtree_color_swap(node->parent, brother); rbtree_right_rotate(tree, node->parent); node = tree->root; } } } rbtree_set_black(node); }
static void rbtree_insert_fixup(rbtree_t *tree, rbtree_node_t *node) { while (rbtree_is_red(node->parent)) { if (node->parent == node->parent->parent->left) { if (rbtree_is_red(node->parent->parent->right)) { rbtree_set_black(node->parent); rbtree_set_black(node->parent->parent->right); rbtree_set_red(node->parent->parent); node = node->parent->parent; } else { if (node == node->parent->right) { node = node->parent; rbtree_left_rotate(tree, node); } rbtree_set_black(node->parent); rbtree_set_red(node->parent->parent); rbtree_right_rotate(tree, node->parent->parent); } } else { if (rbtree_is_red(node->parent->parent->left)) { rbtree_set_black(node->parent); rbtree_set_black(node->parent->parent->left); rbtree_set_red(node->parent->parent); } else { if (node == node->parent->left) { node = node->parent; rbtree_right_rotate(tree, node); } rbtree_set_black(node->parent); rbtree_set_red(node->parent->parent); rbtree_left_rotate(tree, node->parent->parent); } } } rbtree_set_black(tree->root); }
void rbtree_delete(struct rbtree *tree, struct rbnode *node) { struct rbnode **root = &tree->root; struct rbnode *sentinel = tree->sentinel; struct rbnode *subst, *temp, *w; uint8_t red; /* a binary tree delete */ if (node->left == sentinel) { temp = node->right; subst = node; } else if (node->right == sentinel) { temp = node->left; subst = node; } else { subst = rbtree_node_min(node->right, sentinel); if (subst->left != sentinel) { temp = subst->left; } else { temp = subst->right; } } if (subst == *root) { *root = temp; rbtree_black(temp); rbtree_node_init(node); return; } red = rbtree_is_red(subst); if (subst == subst->parent->left) { subst->parent->left = temp; } else { subst->parent->right = temp; } if (subst == node) { temp->parent = subst->parent; } else { if (subst->parent == node) { temp->parent = subst; } else { temp->parent = subst->parent; } subst->left = node->left; subst->right = node->right; subst->parent = node->parent; rbtree_copy_color(subst, node); if (node == *root) { *root = subst; } else { if (node == node->parent->left) { node->parent->left = subst; } else { node->parent->right = subst; } } if (subst->left != sentinel) { subst->left->parent = subst; } if (subst->right != sentinel) { subst->right->parent = subst; } } rbtree_node_init(node); if (red) { return; } /* a delete fixup */ while (temp != *root && rbtree_is_black(temp)) { if (temp == temp->parent->left) { w = temp->parent->right; if (rbtree_is_red(w)) { rbtree_black(w); rbtree_red(temp->parent); rbtree_left_rotate(root, sentinel, temp->parent); w = temp->parent->right; } if (rbtree_is_black(w->left) && rbtree_is_black(w->right)) { rbtree_red(w); temp = temp->parent; } else { if (rbtree_is_black(w->right)) { rbtree_black(w->left); rbtree_red(w); rbtree_right_rotate(root, sentinel, w); w = temp->parent->right; } rbtree_copy_color(w, temp->parent); rbtree_black(temp->parent); rbtree_black(w->right); rbtree_left_rotate(root, sentinel, temp->parent); temp = *root; } } else { w = temp->parent->left; if (rbtree_is_red(w)) { rbtree_black(w); rbtree_red(temp->parent); rbtree_right_rotate(root, sentinel, temp->parent); w = temp->parent->left; } if (rbtree_is_black(w->left) && rbtree_is_black(w->right)) { rbtree_red(w); temp = temp->parent; } else { if (rbtree_is_black(w->left)) { rbtree_black(w->right); rbtree_red(w); rbtree_left_rotate(root, sentinel, w); w = temp->parent->left; } rbtree_copy_color(w, temp->parent); rbtree_black(temp->parent); rbtree_black(w->left); rbtree_right_rotate(root, sentinel, temp->parent); temp = *root; } } } rbtree_black(temp); }
void rbtree_insert(struct rbtree *tree, struct rbnode *node) { struct rbnode **root = &tree->root; struct rbnode *sentinel = tree->sentinel; struct rbnode *temp, **p; /* empty tree */ if (*root == sentinel) { node->parent = NULL; node->left = sentinel; node->right = sentinel; rbtree_black(node); *root = node; return; } /* a binary tree insert */ temp = *root; for (;;) { p = (node->key < temp->key) ? &temp->left : &temp->right; if (*p == sentinel) { break; } temp = *p; } *p = node; node->parent = temp; node->left = sentinel; node->right = sentinel; rbtree_red(node); /* re-balance tree */ while (node != *root && rbtree_is_red(node->parent)) { if (node->parent == node->parent->parent->left) { temp = node->parent->parent->right; if (rbtree_is_red(temp)) { rbtree_black(node->parent); rbtree_black(temp); rbtree_red(node->parent->parent); node = node->parent->parent; } else { if (node == node->parent->right) { node = node->parent; rbtree_left_rotate(root, sentinel, node); } rbtree_black(node->parent); rbtree_red(node->parent->parent); rbtree_right_rotate(root, sentinel, node->parent->parent); } } else { temp = node->parent->parent->left; if (rbtree_is_red(temp)) { rbtree_black(node->parent); rbtree_black(temp); rbtree_red(node->parent->parent); node = node->parent->parent; } else { if (node == node->parent->left) { node = node->parent; rbtree_right_rotate(root, sentinel, node); } rbtree_black(node->parent); rbtree_red(node->parent->parent); rbtree_left_rotate(root, sentinel, node->parent->parent); } } } rbtree_black(*root); }