From: Doug Dunham
Subject: RB-tree example
To: cs4521-1-s2002@d.umn.edu (CS 4521)
Date: Thu, 7 Mar 2002 16:44:22 -0600 (CST)
I have attached below the example that I tried to work out in the lab
session yesterday. I think it is now correct, but please look it over
and tell me if I have made a mistake.
Also, one of the students has found an interactive Java program that
illustrates red-black tree operations. It is at:
http://www.ececs.uc.edu/~franco/C321/html/RedBlack/redblack.html
I have put up a link to it on the "Lab and Homework Assignments" page of
the class web site.
Note that it seems to do things differently than our book, doing rotations
before colorings, for example. It produced the same trees as in the example
below during insertion, but the deletion of node (5) produced a different
result than below, though both are correct red-black trees. There are
different algorithms for red-black tree insertion and deletion than are
presented in our text.
Here is the example of red-black tree insertions and deletions:
Problem 1: insert 9 8 7 3 5 2 into a red-black tree in that order.
Insert 9: z (9) R and is the root going into RB-INSERT-FIXUP
Since p[z] is nil and B, we skip the loop and do line 16, making root B
Insert 8: (9) B
/
z (8) R
Since p[z] is B, we skip the loop (and do line 16, which has no effect).
Insert 7: (9) B This is Case 3, so we change the colors of p[z] and
/ \ p[p[z]], and right-rotate: (8) B
(8) R nil B / \
/ y (7) R (9) R
z (7) R
Insert 3: (8) B This is Case 1, so we change the colors of p[z], y,
/ \ and p[p[z]], and move z up z' (8) R
(7) R (9) R the tree to its grandparent / \
/ y (7) B (9) B
z (3) R /
(3) R
Since p[z'] is B, the loop ends and we color the root B (not shown above).
Insert 5: (8) B This is Case 2, so we move z up to its parent (3)
/ \ and left rotate: (8) B
(7) B (9) B / \
/ \ (7) B (9) B
(3) R nil y / \
\ (5) R nil y
z (5) R /
z (3) R
This falls through to Case 3, which recolors p[z] and p[p[z]], (8) B
and right-rotates: / \
(5) B (9) B
/ \
z (3) R (7) R
Insert 2: (8) B This is Case 1 again, so we change (8) B
/ \ colors of p[z], y, and p[p[z]], and / \
(5) B (9) B move z up the tree to its grandparent z' (5) R (9) B
/ \ / \
(3) R (7) R (3) B (7) B
/ y /
z (2) R (2) R
Since p[z'] is B, the loop ends (and root is colored B -- no effect).
Problem 2: delete 2 5 3 7 8 9 in that order from the tree above.
This is not really a good example, since it doesn't show many cases.
However, it does show that delete doesn't exactly undo what insert does
(as we might suspect, since insertion is always at a leaf, but we may
delete an interior node).
Delete 2 (R): (8) B No fixup is done, since y = (2) was R
/ \
(5) R (9) B
/ \
(3) B (7) B
Delete 5 (R): (8) B First, the key 5 is replaced by its successor, 7,
/ \ then y = the old node (7), which is B, is deleted,
(7) R (9) B so fixup must be done. This is Case 2' in the
/ \ missing "else" clause -- x's sibling, w, and
(3) B nil B both its children (nils) are B, so we color w red
w x and move x up to its parent: (8) B
/ \
Then, since x' is R, we leave the loop and x' (7) R (9) B
color x' B at line 23 (not shown). /
(3) R
Delete 3 (R): (8) B No fixup is done, since y = (3) was R.
/ \
(7) B (9) B
Delete 7 (B): (8) B This is Case 2 (x's sibling, w, and x' (8) B
/ \ both its children (nils) are B), so \
nil B (9) B so we color w red and move x up to (9) R
x w its parent:
Since x' is the root, the loop ends (and x' is colored B -- no effect).
Delete 8 (B): (9) B Key 8 is replaced by its successor, 9, and y =
the old node (9) is deleted and no fixup is done,
since y was R.
Delete 9 (B): root becomes nil. In RB-DELETE, x becomes the right child
of the old node (9), which is nil, and
the root becomes x in line 9. So the
loop is not entered in RB-DELETE-FIXUP
and we are done.