Fundamental Algorithms - Binary Search Trees
Fundamental Algorithms - Binary Search Trees
Aurelian Nicola
March 1, 2019
2 Traversing
There are three ways to traverse binary search trees:
1
1. Inorder tree walk – visit the left subtree, the root, and right subtree.
2. Preorder tree walk – visit the root, the left subtree and right subtree.
3. Postorder tree walk – visit the left subtree, the right subtree, and the
root.
Inorder-Tree-Walk(x)
1 if x 6= NIL
2 then Inorder-Tree-Walk(left[x])
3 print key[x] /* or some other operation on x */
4 Inorder-Tree-Walk(right[x])
Preorder-Tree-Walk(x)
1 if x 6= NIL
2 then print key[x]
3 Preorder-Tree-Walk(left[x])
4 Preorder-Tree-Walk(right[x])
Postorder-Tree-Walk(x)
1 if x 6= NIL
2 then Postorder-Tree-Walk(left[x])
3 Postorder-Tree-Walk(right[x])
4 print key[x]
3 Querying
3.1 Search
The Tree-Search algorithm comes in two flavours: the recursive and the
iterative approaches. In the recursive approach, we examine the input node
x and compare its key with the key we are looking for, k. If it matches,
2
then we have found a node with the correct key; and can therefore return x.
Otherwise, depending on the value of k and key[x], the node we are after is
either in the left subtree or right subtree of node x.
Tree-Search(x, k)
1 if x = NIL or k = key[x]
2 then return x
3 if k < key[x]
4 then return Tree-Seach(left[x], k)
5 else return Tree-Seach(right[x], k)
Iterative-Tree-Search(x, k)
1 while x 6= NIL and k 6= key[x]
2 do if k < key[x]
3 then x ← left[x]
4 else x ← right[x]
5 return x
3
Tree-Minimum(x)
1 while left[x] 6= NIL
2 do x ← left[x]
3 return x
Tree-Maximum(x)
1 while right[x] 6= NIL
2 do x ← right[x]
3 return x
3.3 Successor
The successor of a node x is the node with the next biggest key. Essentially,
this is the minimum of all the nodes with equal or greater keys. If node x
has a right sub-tree R, then its successor is the minimum of R. Otherwise,
its successor must be the lowest ancestor of x whose left child is either an
ancestor of x or x itself.
Tree-Successor(x)
1 if right[x] 6= NIL
2 then return Tree-Minimum(right[x])
3 y ← p[x]
4 while y 6= NIL and x = right[y]
5 do x ← y
6 y ← p[y]
7 return y
4 Data Manipulation
4.1 Insert
Tree-Insert inserts a node z into tree T . The algorithm starts at the root
of the tree and traverses down the tree following the rules of binary search
4
trees. If the node to be inserted is smaller, then it has to be inserted into
the left subtree, else it should be inserted in the right subtree. The process
continues until the appropriate subtree does not exist. That is to say, the
left/right child of the current node is NIL. Node z is then inserted into the
tree as the appropriate child of the current node.
Tree-Insert(T, z)
1 y ← NIL
2 x ← root[T ]
3 while x 6= NIL
4 do y ← x
5 if key[z] < key[x]
6 then x ← left[x]
7 else x ← right[x]
8 p[z] ← y
9 if y = NIL
10 then root[T ] ← z /* The tree was empty. */
11 else if key[z] < key[y]
12 then left[y] ← z
13 else right[y] ← z
4.2 Delete
Tree-Delete deletes a node z from tree T . There are three possible states
for node z prior to deletion. It may have no children, one child, or two
children. The Tree-Delete algorithm works by considering each of these
possibilities and behaving accordingly. If z has no children, then it is simply
removed from the tree. For the case where z has one child, p[z]’s left/right
child pointer that is currently directed at z is redirected to z’s child (see
Figure ??). Lastly, if z has two children, it’s successor is removed from the
tree and is used to replace z. The algorithm follows:
5
Figure 2: Tree-Delete. If z has one child, it is simply spliced out of the
tree. Since z can be the left or right child of its parent p, and it may have a
left or right child c itself, there are four possibilities (a), (b), (c), and (d).
Tree-Delete(T, z)
1 if left[z] = NIL or right[z] = NIL
2 then y ← z
3 else y ← Tree-Successor(z)
4 if left[y] 6= NIL
5 then x ← left[y]
6 else x ← right[y]
7 if x 6= NIL
8 then p[x] ← p[y]
9 if p[y] = NIL
10 then root[T ] ← x
11 else if y = left[p[y]]
12 then left[p[y]] ← x
13 else right[p[y]] ← x
14 if y 6= z
15 then key[z] ← key[y]
16 copy y’s satellite data into z
17 return y
6
Figure 3: Tree-Delete. If z has two children, we remove its successor s.
Node s is guaranteed to have at most one child because it is the minimum of
sub-tree R. It’s removal is thus either of the other two Tree-Delete cases.
When this is done, s is used to replace z.