Tree Traversal
Tree Traversal
Searching
Red-Black and Other Dynamically BalancedTrees
Searching - Re-visited
• Binary tree O(log n) if it stays balanced
• Simple binary tree good for static collections
• Low (preferably zero) frequency of insertions/deletions
but my collection keeps changing!
• It’s dynamic
• Need to keep the tree balanced
• First, examine some basic tree operations
• Useful in several ways!
Tree Traversal
• Traversal = visiting every node of a tree
• Three basic alternatives
Pre-order
• Root
• Left sub-tree
• Right sub-tree
x A +x+BC xDE F
L R
L R L
Tree Traversal
• Traversal = visiting every node of a tree
• Three basic alternatives
In-order
• Left sub-tree
• Root
• Right sub-tree
11
Ax B+C xDxE +F
L
L R
Tree Traversal
• Traversal = visiting every node of a tree
• Three basic alternatives
Post-order
• Left sub-tree 11
• Right sub-tree
• Root
A B C+ D Exx F+x
L
L R
Tree Traversal
Post-order 11
• Left sub-tree
• Right sub-tree
• Root
Reverse-Polish
(A (((BC+)(DEx) x) F +)x )
• Normal algebraic form
(A x(((B+C)(DxE))+F))
= which traversal?
Trees - Searching
• Binary search tree
• Produces a sorted list by in-order traversal
• Essentially,
height 2 black height
• Search time
O( log n )
Trees - Red-Black Trees
• Data structure
• As we’ll see, nodes in red-black trees need to know their
parents,
• so we need this data structure
struct t_red_black_node {
enum { red, black } colour;
void *item; Same as a
struct t_red_black_node *left, binary tree
with these two
*right,
attributes
*parent; added
}
Trees - Insertion
• Insertion of a new node
• Requires a re-balance of the tree
rb_insert( Tree T, node x ) {
/* Insert in the tree in the usual way */
tree_insert( T, x );
/* Now restore the red-black property */
x->colour = red;
while ( (x != T->root) && (x->parent->colour == red) ) {
Insert
if (node
x->parent == x->parent->parent->left ) {
4 /* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
Mark itifred
( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour
Label the current node = black;
y->colour = black;
x
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
Trees - Insertion
rb_insert( Tree T, node x ) {
/* Insert in the tree in the usual way */
tree_insert( T, x );
/* Now restore the red-black property */
x->colour = red;
while ( (x != T->root) && (x->parent->colour == red) )
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
While we haven’t reached the root
y = x->parent->parent->right;
if ( y->colour == red ) {
and x’s parent
/* caseis 1red
- change the colours */
x->parent->colour = black;
y->colour = black;
x->parent
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
Trees - Insertion
rb_insert( Tree T, node x ) {
/* Insert in the tree in the usual way */
tree_insert( T, x );
/* Now restore the red-black property */
x->colour = red;
while ( (x != T->root) && (x->parent->colour == red) )
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
If x is to the
y =left of it’s granparent
x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
x->parent->parent
y->colour = black;
x->parent->parent->colour = red;
x->parent
/* Move x up the tree */
x = x->parent->parent;
Trees - Insertion
/* Now restore the red-black property */
x->colour = red;
while ( (x != T->root) && (x->parent->colour == red) )
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle'
y = x->parent->parent->right;
if ( y->colour == red ) {
y is x’s
/* right
case uncle
1 - change
the colours */
x->parent->colour = black;
y->colour = black;
x->parent->parent
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent
x->parent->parent;
right “uncle”
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) )
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle'
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
y->colour = black;
x->parent->parent->colour = red;
/* Move x up the tree */
If the uncle
is
x red, change
= x->parent->parent;
x->parent->parent
the colours of y, the grand-parent
and the parent
x->parent
right “uncle”
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) )
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle'
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
y->colour = black;
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
y->colour = black;
x’sx->parent->parent->colour
parent is a left again, = red;
/*mark
Move x’s
x up the tree */
uncle
x = x->parent->parent;
but the uncle is black this time
New x
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
.. but the uncle is black this time
y->colour = black;
and x is to the right of it’s parent
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
else {
/* y is a black node */
if ( x == x->parent->right ) {
/* and x is to the right */
/* case 2 - move x up and rotate */
x = x->parent;
left_rotate( T, x );
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
.. So move x up and
y->colour = black;
rotate about x as root ...
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
else {
/* y is a black node */
if ( x == x->parent->right ) {
/* and x is to the right */
/* case 2 - move x up and rotate */
x = x->parent;
left_rotate( T, x );
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
y->colour = black;
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
else {
/* y is a black node */
if ( x == x->parent->right ) {
/* and x is to the right */
/* case 2 - move x up and rotate */
x = x->parent;
left_rotate( T, x );
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
y->colour = black;
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
else {
/* y is a black node */
if ( x == x->parent->right ) {
/* and x is to the right */
.. but
/* case 2 - move x x’s
up parent is still red
and rotate */ ...
x = x->parent;
left_rotate( T, x );
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
.. The uncle is black ..
y->colour = black;
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
else { uncle
/* y is a black node */
if ( x == x->parent->right ) {
/* and x is to the right */
/* case 2 - move x up and rotate */
.. and x is to the left of its parent
x = x->parent;
left_rotate( T, x );
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
y->colour = black;
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
.. So we have the final case ..
else {
/* y is a black node */
if ( x == x->parent->right ) {
/* and x is to the right */
/* case 2 - move x up and rotate */
x = x->parent;
left_rotate( T, x );
else { /* case 3 */
x->parent->colour = black;
x->parent->parent->colour = red;
right_rotate( T, x->parent->parent );
}
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
y->colour = black;
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
.. Change colours
else {
/* y is a black node */
and rotate ..
if ( x == x->parent->right ) {
/* and x is to the right */
/* case 2 - move x up and rotate */
x = x->parent;
left_rotate( T, x );
else { /* case 3 */
x->parent->colour = black;
x->parent->parent->colour = red;
right_rotate( T, x->parent->parent );
}
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
y->colour = black;
x->parent->parent->colour = red;
/* Move x up the tree */
x = x->parent->parent;
else {
/* y is a black node */
if ( x == x->parent->right ) {
/* and x is to the right */
/* case 2 - move x up and rotate */
x = x->parent;
left_rotate( T, x );
else { /* case 3 */
x->parent->colour = black;
x->parent->parent->colour = red;
right_rotate( T, x->parent->parent );
}
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
y->colour = black;
This is now a red-black tree ..
x->parent->parent->colour = red;
/* Move x up the tree */
So we’re finished!
x = x->parent->parent;
else {
/* y is a black node */
if ( x == x->parent->right ) {
/* and x is to the right */
/* case 2 - move x up and rotate */
x = x->parent;
left_rotate( T, x );
else { /* case 3 */
x->parent->colour = black;
x->parent->parent->colour = red;
right_rotate( T, x->parent->parent );
}
Trees - Insertion
while ( (x != T->root) && (x->parent->colour == red) ) {
if ( x->parent == x->parent->parent->left ) {
/* If x's parent is a left, y is x's right 'uncle' */
y = x->parent->parent->right;
if ( y->colour == red ) {
/* case 1 - change the colours */
x->parent->colour = black;
There’s an equivalent set of
y->colour = black;
x->parent->parent->colour = red;
cases when the parent is to
/* Move x up the tree */
x = x->parent->parent;
the right of the grandparent!
else {
/* y is a black node */
if ( x == x->parent->right ) {
/* and x is to the right */
/* case 2 - move x up and rotate */
x = x->parent;
left_rotate( T, x );
else { /* case 3 */
x->parent->colour = black;
x->parent->parent->colour = red;
right_rotate( T, x->parent->parent );
}
}
else ....
Red-black trees - Analysis
• Addition
• Insertion Comparisons O(log n)
• Fix-up
• At every stage,
x moves up the tree
at least one level O(log n)
• Overall O(log n)
• Deletion
• Also O(log n)
• More complex
• ... but gives O(log n) behaviour in dynamic cases
Red Black Trees - What you need to know?
• Code?
• This is not a course for masochists!
• You can find it in a text-book
• You need to know
• The algorithm exists
• What it’s called
• When to use it
• ie what problem does it solve?
• Its complexity
• Basically how it works
• Where to find an implementation
• How to transform it to your application