void rbtree_remove_fixup(rb_tree * tree, rb_node * node) { rb_node *curr_node = node; rb_node *sibling; while (curr_node != tree->root && curr_node->color == black) { /* Get a pointer to the current node's sibling (notice * that the node's parent must exist, since the node * is not the root). */ if (curr_node == curr_node->parent->left) { /* If the current node is a left child, its * sibling is the right child of the parent. */ sibling = curr_node->parent->right; /* Check the sibling's color. Notice that NULL * nodes are treated as if they are colored * black. */ if (sibling && sibling->color == red) { /* In case the sibling is red, color * it black and rotate. Then color * the parent red (the grandparent is * now black) */ sibling->color = black; curr_node->parent->color = red; rbtree_rotate_left(tree, curr_node->parent); sibling = curr_node->parent->right; } if (sibling && (!(sibling->left) || sibling->left->color == black) && (!(sibling->right) || sibling->right->color == black)) { /* If the sibling has two black * children, color it red */ sibling->color = red; if (curr_node->parent->color == red) { /* If the parent is red, we * can safely color it black * and terminate the fix * process. */ curr_node->parent->color = black; /* In order to stop the while loop */ curr_node = tree->root; } else { /* The black depth of the * entire sub-tree rooted at * the parent is now too small * - fix it up recursively. */ curr_node = curr_node->parent; } } else { if (!sibling) { /* Take special care of the * case of a NULL sibling */ if (curr_node->parent->color == red) { curr_node->parent->color = black; /* In order to stop * the while loop */ curr_node = tree->root; } else { curr_node = curr_node->parent; } } else { /* In this case, at least one * of the sibling's children * is red. It is therfore * obvious that the sibling * itself is black. */ if (sibling->right && sibling->right->color == red) { /* If the right child * of the sibling is * red, color it black * and rotate around * the current parent. */ sibling->right->color = black; rbtree_rotate_left(tree, curr_node-> parent); } else { /* If the left child * of the sibling is * red, rotate around * the sibling, then * rotate around the * new sibling of our * current node. */ rbtree_rotate_right(tree, sibling); sibling = curr_node->parent->right; rbtree_rotate_left(tree, sibling); } /* It is now safe to color the * parent black and to * terminate the fix process. */ if (curr_node->parent->parent) curr_node->parent->parent-> color = curr_node->parent->color; curr_node->parent->color = black; /* In order to stop the while loop */ curr_node = tree->root; } } } else { /* If the current node is a right child, its * sibling is the left child of the parent. */ sibling = curr_node->parent->left; /* Check the sibling's color. Notice that NULL * nodes are treated as if they are colored * black. */ if (sibling && sibling->color == red) { /* In case the sibling is red, color * it black and rotate. Then color * the parent red (the grandparent is * now black). */ sibling->color = black; curr_node->parent->color = red; rbtree_rotate_right(tree, curr_node->parent); sibling = curr_node->parent->left; } if (sibling && (!(sibling->left) || sibling->left->color == black) && (!(sibling->right) || sibling->right->color == black)) { /* If the sibling has two black children, color it red */ sibling->color = red; if (curr_node->parent->color == red) { /* If the parent is red, we * can safely color it black * and terminate the fix-up * process. */ curr_node->parent->color = black; /* In order to stop the while * loop */ curr_node = tree->root; } else { /* The black depth of the * entire sub-tree rooted at * the parent is now too small * - fix it up recursively. */ curr_node = curr_node->parent; } } else { if (!sibling) { /* Take special care of the * case of a NULL sibling */ if (curr_node->parent->color == red) { curr_node->parent->color = black; /* In order to stop * the while loop */ curr_node = tree->root; } else { curr_node = curr_node->parent; } } else { /* In this case, at least one * of the sibling's children is * red. It is therfore obvious * that the sibling itself is * black. */ if (sibling->left && sibling->left->color == red) { /* If the left child * of the sibling is * red, color it black * and rotate around * the current parent */ sibling->left->color = black; rbtree_rotate_right(tree, curr_node-> parent); } else { /* If the right child * of the sibling is * red, rotate around * the sibling, then * rotate around the * new sibling of our * current node */ rbtree_rotate_left(tree, sibling); sibling = curr_node->parent->left; rbtree_rotate_right(tree, sibling); } /* It is now safe to color the * parent black and to * terminate the fix process. */ if (curr_node->parent->parent) curr_node->parent->parent-> color = curr_node->parent->color; curr_node->parent->color = black; /* In order to stop the while loop */ curr_node = tree->root; } } } } /* The root can always be colored black */ curr_node->color = black; }
void rbtree_insert_fixup(rb_tree * tree, rb_node * node) { /* Fix the red-black propreties. We may have inserted a red * leaf as the child of a red parent - so we have to fix the * coloring of the parent recursively. */ rb_node *curr_node = node; rb_node *grandparent; rb_node *uncle; assert(node && node->color == red); while (curr_node != tree->root && curr_node->parent->color == red) { /* Get a pointer to the current node's grandparent * (the root is always black, so the red parent must * have a parent). */ grandparent = curr_node->parent->parent; if (curr_node->parent == grandparent->left) { /* If the red parent is a left child, the * uncle is the right child of the grandparent. */ uncle = grandparent->right; if (uncle && uncle->color == red) { /* If both parent and uncle are red, * color them black and color the * grandparent red. In case of a NULL * uncle, treat it as a black node */ curr_node->parent->color = black; uncle->color = black; grandparent->color = red; /* Move to the grandparent */ curr_node = grandparent; } else { /* Make sure the current node is a * right child. If not, left-rotate the * parent's sub-tree so the parent * becomes the right child of the * current node (see _rotate_left). */ if (curr_node == curr_node->parent->right) { curr_node = curr_node->parent; rbtree_rotate_left(tree, curr_node); } /* Color the parent black and the * grandparent red */ curr_node->parent->color = black; grandparent->color = red; /* Right-rotate the grandparent's * sub-tree */ rbtree_rotate_right(tree, grandparent); } } else { /* If the red parent is a right child, the * uncle is the left child of the grandparent. */ uncle = grandparent->left; if (uncle && uncle->color == red) { /* If both parent and uncle are red, * color them black and color the * grandparent red. In case of a NULL * uncle, treat it as a black node */ curr_node->parent->color = black; uncle->color = black; grandparent->color = red; /* Move to the grandparent */ curr_node = grandparent; } else { /* Make sure the current node is a * left child. If not, right-rotate * the parent's sub-tree so the parent * becomes the left child of the * current node. */ if (curr_node == curr_node->parent->left) { curr_node = curr_node->parent; rbtree_rotate_right(tree, curr_node); } /* Color the parent black and the * grandparent red */ curr_node->parent->color = black; grandparent->color = red; /* Left-rotate the grandparent's * sub-tree */ rbtree_rotate_left(tree, grandparent); } } } /* Make sure that the root is black */ tree->root->color = black; }
/*! * Fix-up the red-black tree properties after a removal operation * * \param tree The tree * * \param node The child of the node that has just been removed from the tree */ void rbtree_remove_fixup(rbtree_t * tree, rbnode_t * node) { rbnode_t * curr_node = node; rbnode_t * sibling; while (curr_node != tree->root && curr_node->color == RB_BLACK) { /* Get a pointer to the current node's sibling (notice that the node's * parent must exist, since the node is not the root). */ if (curr_node == curr_node->parent->left) { /* If the current node is a left child, its sibling is the right * child of the parent. */ sibling = curr_node->parent->right; /* Check the sibling's color. Notice that NULL nodes are treated * as if they are colored black. */ if (sibling && sibling->color == RB_RED) { /* In case the sibling is red, color it black and rotate. * Then color the parent red (and the grandparent is now black). */ sibling->color = RB_BLACK; curr_node->parent->color = RB_RED; rbtree_rotate_left(tree, curr_node->parent); sibling = curr_node->parent->right; } if (sibling && (!(sibling->left) || sibling->left->color == RB_BLACK) && (!(sibling->right) || sibling->right->color == RB_BLACK)) { /* If the sibling has two black children, color it red */ sibling->color = RB_RED; if (curr_node->parent->color == RB_RED) { /* * If the parent is red, we can safely color it black * and terminate the fix-up process. */ curr_node->parent->color = RB_BLACK; /* In order to stop the while loop */ curr_node = tree->root; } else { /* * The black depth of the entire sub-tree rooted at the parent is * now too small - fix it up recursively. */ curr_node = curr_node->parent; } } else { if (!sibling) { /* Take special care of the case of a NULL sibling */ if (curr_node->parent->color == RB_RED) { curr_node->parent->color = RB_BLACK; /* In order to stop the while loop */ curr_node = tree->root; } else { curr_node = curr_node->parent; } } else { /* In this case, at least one of the sibling's children is red. * It is therfore obvious that the sibling itself is black. */ if (sibling->right && sibling->right->color == RB_RED) { /* * If the right child of the sibling is red, color it * black and rotate around the current parent. */ sibling->right->color = RB_BLACK; rbtree_rotate_left(tree, curr_node->parent); } else { /* If the left child of the sibling is red, rotate * around the sibling, then rotate around the new * sibling of our current node. */ rbtree_rotate_right(tree, sibling); sibling = curr_node->parent->right; rbtree_rotate_left(tree, sibling); } /* * It is now safe to color the parent black and * to terminate the fix-up process. */ if (curr_node->parent->parent) curr_node->parent->parent->color = curr_node->parent->color; curr_node->parent->color = RB_BLACK; /* In order to stop the while loop */ curr_node = tree->root; } } } else { /* * If the current node is a right child, its sibling is the left * child of the parent. */ sibling = curr_node->parent->left; /* * Check the sibling's color. Notice that NULL nodes are treated * as if they are colored black. */ if (sibling && sibling->color == RB_RED) { /* * In case the sibling is red, color it black and rotate. * Then color the parent red (and the grandparent is now black). */ sibling->color = RB_BLACK; curr_node->parent->color = RB_RED; rbtree_rotate_right(tree, curr_node->parent); sibling = curr_node->parent->left; } if (sibling && (!(sibling->left) || sibling->left->color == RB_BLACK) && (!(sibling->right) || sibling->right->color == RB_BLACK)) { /* If the sibling has two black children, color it red */ sibling->color = RB_RED; if (curr_node->parent->color == RB_RED) { /* * If the parent is red, we can safely color it black * and terminate the fix-up process. */ curr_node->parent->color = RB_BLACK; /* In order to stop the while loop */ curr_node = tree->root; } else { /* * The black depth of the entire sub-tree rooted at * the parent is now too small - fix it up recursively. */ curr_node = curr_node->parent; } } else { if (!sibling) { /* Take special care of the case of a NULL sibling */ if (curr_node->parent->color == RB_RED) { curr_node->parent->color = RB_BLACK; /* In order to stop the while loop */ curr_node = tree->root; } else { curr_node = curr_node->parent; } } else { /* In this case, at least one of the sibling's children is red. * It is therfore obvious that the sibling itself is black. */ if (sibling->left && sibling->left->color == RB_RED) { /* If the left child of the sibling is red, color it * black and rotate around the current parent */ sibling->left->color = RB_BLACK; rbtree_rotate_right(tree, curr_node->parent); } else { /* * If the right child of the sibling is red, rotate * around the sibling, then rotate around the new * sibling of our current node. */ rbtree_rotate_left(tree, sibling); sibling = curr_node->parent->left; rbtree_rotate_right(tree, sibling); } /* * It is now safe to color the parent black and to * terminate the fix-up process. */ if (curr_node->parent->parent) curr_node->parent->parent->color = curr_node->parent->color; curr_node->parent->color = RB_BLACK; /* In order to stop the while loop */ curr_node = tree->root; } } } } /* The root can always be colored black */ curr_node->color = RB_BLACK; }
static void rbtree_insert_fixup(rbtree_t *rbtree, rbnode_t *node) { rbnode_t *uncle; /* While not at the root and need fixing... */ while (node != rbtree->root && node->parent->color == RED) { /* If our parent is left child of our grandparent... */ if (node->parent == node->parent->parent->left) { uncle = node->parent->parent->right; /* If our uncle is red... */ if (uncle->color == RED) { /* Paint the parent and the uncle black... */ node->parent->color = BLACK; uncle->color = BLACK; /* And the grandparent red... */ node->parent->parent->color = RED; /* And continue fixing the grandparent */ node = node->parent->parent; } else { /* Our uncle is black... */ /* Are we the right child? */ if (node == node->parent->right) { node = node->parent; rbtree_rotate_left(rbtree, node); } /* Now we're the left child, repaint and rotate... */ node->parent->color = BLACK; node->parent->parent->color = RED; rbtree_rotate_right(rbtree, node->parent->parent); } } else { uncle = node->parent->parent->left; /* If our uncle is red... */ if (uncle->color == RED) { /* Paint the parent and the uncle black... */ node->parent->color = BLACK; uncle->color = BLACK; /* And the grandparent red... */ node->parent->parent->color = RED; /* And continue fixing the grandparent */ node = node->parent->parent; } else { /* Our uncle is black... */ /* Are we the right child? */ if (node == node->parent->left) { node = node->parent; rbtree_rotate_right(rbtree, node); } /* Now we're the right child, repaint and rotate... */ node->parent->color = BLACK; node->parent->parent->color = RED; rbtree_rotate_left(rbtree, node->parent->parent); } } } rbtree->root->color = BLACK; }
/*! * Fix-up the red-black tree properties after an insertion operation * so it maintains the red-black properties. * * \param tree The tree * * \param node The node that has just been inserted to the tree * * \pre The color of node must be red */ void rbtree_insert_fixup ( rbtree_t * tree, rbnode_t * node ) { /* * Fix the red-black propreties: we may have inserted a red * leaf as the child of a red parent - so we have to fix the * coloring of the parent recursively. */ rbnode_t * curr_node = node; rbnode_t * grandparent; rbnode_t *uncle; ASSERT(node && node->color == RB_RED); while (curr_node != tree->root && curr_node->parent->color == RB_RED) { /* * Get a pointer to the current node's grandparent * (notice the root is always black, so the red * parent must have a parent). */ grandparent = curr_node->parent->parent; if (curr_node->parent == grandparent->left) { /* If the red parent is a left child, the uncle is the right child of * the grandparent. */ uncle = grandparent->right; if (uncle && uncle->color == RB_RED) { /* If both parent and uncle are red, color them black and color the * grandparent red. * In case of a NULL uncle, we treat it as a black node. */ curr_node->parent->color = RB_BLACK; uncle->color = RB_BLACK; grandparent->color = RB_RED; /* Move to the grandparent */ curr_node = grandparent; } else { /* Make sure the current node is a right child. If not, left-rotate * the parent's sub-tree so the parent becomes the right child of the * current node (see _rotate_left). */ if (curr_node == curr_node->parent->right) { curr_node = curr_node->parent; rbtree_rotate_left(tree, curr_node); } /* Color the parent black and the grandparent red */ curr_node->parent->color = RB_BLACK; grandparent->color = RB_RED; /* Right-rotate the grandparent's sub-tree */ rbtree_rotate_right(tree, grandparent); } } else { /* If the red parent is a right child, the uncle is the left child of * the grandparent. */ uncle = grandparent->left; if (uncle && uncle->color == RB_RED) { /* If both parent and uncle are red, color them black and color the * grandparent red. * In case of a NULL uncle, we treat it as a black node. */ curr_node->parent->color = RB_BLACK; uncle->color = RB_BLACK; grandparent->color = RB_RED; /* Move to the grandparent */ curr_node = grandparent; } else { /* Make sure the current node is a left child. If not, right-rotate * the parent's sub-tree so the parent becomes the left child of the * current node. */ if (curr_node == curr_node->parent->left) { curr_node = curr_node->parent; rbtree_rotate_right(tree, curr_node); } /* Color the parent black and the grandparent red */ curr_node->parent->color = RB_BLACK; grandparent->color = RB_RED; /* Left-rotate the grandparent's sub-tree */ rbtree_rotate_left(tree, grandparent); } } } /* Make sure that the root is black */ tree->root->color = RB_BLACK; }