SKEDSOFT

Design Analysis Of Algorithm

Deletion: Like the other basic operations on an n-node red-black tree, deletion of a node takes time O(lg n). Deleting a node from a red-black tree is only slightly more complicated than inserting a node.

The procedure RB-DELETE is a minor modification of the TREE-DELETE procedure.  After splicing out a node, it calls an auxiliary procedure RB-DELETE-FIXUP that changes colors and performs rotations to restore the red-black properties.

	RB-DELETE(T, z)
 1 if left[z] = nil[T] or right[z] = nil[T]
 2    then y  z
 3    else y  TREE-SUCCESSOR(z)
 4 if left[y]  nil[T]
 5    then x  left[y]
 6    else x  right[y]
 7 p[x]  p[y]
 8 if p[y] = nil[T]
 9    then root[T]  x
10    else if y = left[p[y]]
11            then left[p[y]]  x
12            else right[p[y]]  x
13 if y 3 z
14    then key[z]  key[y]
15         copy y's satellite data into z
16 if color[y] = BLACK
17    then RB-DELETE-FIXUP(T, x)
18 return y

There are three differences between the procedures TREE-DELETE and RB-DELETE. First, all references to NIL in TREE-DELETE are replaced by references to the sentinel nil[T ] in RB-DELETE. Second, the test for whether x is NIL in line 7 of TREE-DELETE is removed, and the assignment p[x] p[y] is performed unconditionally in line 7 of RB-DELETE. Thus, if x is the sentinel nil[T], its parent pointer points to the parent of the spliced-out node y. Third, a call to RB-DELETE-FIXUP is made in lines 16-17 if y is black. If y is red, the red-black properties still hold when y is spliced out, for the following reasons:

  • no black-heights in the tree have changed,

  • no red nodes have been made adjacent, and

  • since y could not have been the root if it was red, the root remains black.

The node x passed to RB-DELETE-FIXUP is one of two nodes: either the node that was y's sole child before y was spliced out if y had a child that was not the sentinel nil[T ], or, if y had no children, x is the sentinel nil[T ]. In the latter case, the unconditional assignment in line 7 guarantees that x's parent is now the node that was previously y's parent, whether x is a key-bearing internal node or the sentinel nil[T].

We can now examine how the procedure RB-DELETE-FIXUP restores the red-black properties to the search tree.

	RB-DELETE-FIXUP(T, x)
 1 while x  root[T] and color[x] = BLACK
 2     do if x = left[p[x]]
 3           then w  right[p[x]]
 4                if color[w] = RED
 5                   then color[w]  BLACK                          Case 1
 6                        color[p[x]]  RED                         Case 1
 7                        LEFT-ROTATE(T, p[x])                      Case 1
 8                        w  right[p[x]]                           Case 1
 9                if color[left[w]] = BLACK and color[right[w]] = BLACK
10                   then color[w]  RED                            Case 2
11                        x p[x]                                    Case 2
12                   else if color[right[w]] = BLACK
13                           then color[left[w]]  BLACK            Case 3
14                                color[w]  RED                    Case 3
15                                RIGHT-ROTATE(T, w)                Case 3
16                                w  right[p[x]]                   Case 3
17                         color[w]  color[p[x]]                   Case 4
18                         color[p[x]]  BLACK                      Case 4
19                         color[right[w]]  BLACK                  Case 4
20                         LEFT-ROTATE(T, p[x])                     Case 4
21                         x  root[T]                              Case 4
22        else (same as then clause with "right" and "left" exchanged)
23 color[x]  BLACK

If the spliced-out node y in RB-DELETE is black, three problems may arise. First, if y had been the root and a red child of y becomes the new root, we have violated property 2. Second, if both x and p[y] (which is now also p[x]) were red, then we have violated property 4. Third, y's removal causes any path that previously contained y to have one fewer black node. Thus, property 5 is now violated by any ancestor of y in the tree. We can correct this problem by saying that node x has an "extra" black. That is, if we add 1 to the count of black nodes on any path that contains x, then under this interpretation, property 5 holds. When we splice out the black node y, we "push" its blackness onto its child. The problem is that now node x is neither red nor black, thereby violating property 1. Instead, node x is either "doubly black" or "red-and-black," and it contributes either 2 or 1, respectively, to the count of black nodes on paths containing x. The color attribute of x will still be either RED (if x is red-and-black) or BLACK (if x is doubly black). In other words, the extra black on a node is reflected in x's pointing to the node rather than in the color attribute.