Red-Black Tree Operations
Explore the key operations to add and remove nodes in red-black trees, including fixing violations of tree properties through rotations and recoloring. Understand how these maintain balanced search trees with guaranteed O(log n) performance. This lesson helps you grasp complex balancing techniques fundamental for efficient data storage and retrieval.
Addition
To implement add(x) in a RedBlackTree, we perform a standard BinarySearchTree insertion to add a new leaf, u, with u.x = x and set u.colour = red. Note that this does not change the black height of any node, so it
does not violate the black-height property. It may, however, violate the
left-leaning property (if u is the right child of its parent), and it may
violate the no-red-edge property (if u’s parent is red). To restore these
properties, we call the method add_fixup(u).
A single round in the process of fixing Property 2 after an insertion is illustrated in the below illustration:
The add_fixup(u) method takes as input a
node u whose color is red and which may violate the no-red-edge property and/or the left-leaning property. The following discussion is probably impossible to follow without referring to the above figure or recreating it on
a piece of paper. Indeed, the reader may wish to study the above figure before
continuing.
If u is the root of the tree, then we can color u black to restore both
properties. If u’s sibling is also red, then u’s parent must be black, so both
the left-leaning and no-red-edge properties already hold.
Otherwise, we first determine if u’s parent, w, violates the left-leaning
property and, if so, perform a flip_left(w) operation and set u = w. This leaves us in a well-defined state: u is the left child of its parent, w, so w now satisfies the left-leaning property. All that remains is to ensure the no-red-edge property at u. We only have to worry about the case in which
w is red, since otherwise u already satisfies the no-red-edge property.
Since we are not done yet, u is red and w is red. The no-red-edge property (which is only violated by u and not by w) implies that u’s grandparent g exists and is black. If g’s right child is red, then the left-leaning
property ensures that both g’s children are red, and a call to push_black(g)
makes g red and w black. This restores the no-red-edge property at u, but may cause it to be violated at g, so the whole process starts over with
u = g.
If g's right child is black, then a call to flip_right(g) makes w the
(black) parent of g and gives w two red children, u and g. This ensures
that u satisfies the no-red-edge property and g satisfies the left-leaning property. In this case we can stop.
The add_fixup(u) method takes constant time per iteration and each iteration either finishes or moves u closer to the root. Therefore,
the add_fixup(u) method finishes after iterations in time.
Removal
The remove(x) operation in a RedBlackTree is the most complicated to
implement, and this is true of all known red-black tree variants. Just
like the remove(x) operation in a BinarySearchTree, this operation boils
down to finding a node w with only one child, u, and splicing w out of the
tree by having w.parent adopt u.
The problem with this is that, if w is black, then the black-height
property will now be violated at w.parent. We may avoid this problem, temporarily, by adding w.colour to u.colour. Of ...