Title: Binary Search Trees
1Binary Search Trees Reminder It is not possible
to apply a binary search algorithm to data stored
in a linked list because the structure is not a
random access structure there is no way of
directly accessing the item in the middle of
the structure (a key operation in the binary
search algorithm).
2A binary search tree is a binary tree such that
for every node in the tree, all of the entries in
the left sub-tree (if any) are smaller than the
entry in the node and all of the entries in the
right sub-tree (if any) are larger than the entry
in the node.
not a binary search tree
a binary search tree
Note there is no requirement that a binary
search tree be a complete binary tree.
3Common operations on Binary Search Trees
(BST) Searching for an item in a BSTAlgorithm
if tree is empty, item is not present
otherwise if item is in root of tree, were done
otherwise if item is less than item in root,
search left sub-tree otherwise search right
sub-tree
4Implementation In the following discussion we
will assume that the nodes of the binary search
tree are represented by templatelt typename Key,
typename Value gtstruct BNode Key key
Value value BNode left BNode right
5Implementation search templatelt typename Key,
typename Value gtvoid search( BNodelt Key, Value
gt root, const Key key, Value value )
6Implementation search templatelt typename Key,
typename Value gtvoid search( BNodelt Key, Value
gt root, const Key key, Value value )
if (root NULL) return if (key
root-gtkey) value root-gtvalue else if
(key lt root-gtkey) search(root-gtleft, key,
value) else search(root-gtright, key,
value)
7The recursive version is very concise and
elegant. For comparison we will now write an
iterative version templatelt typename Key,
typename Value gtvoid search( BNodelt Key, Value
gt root, const Key key, Value value )
while (root ! NULL key ! root-gtkey)
if (key lt root-gtkey) root root-gtleft
else root root-gtright if
(root ! NULL) value root-gtvalue
8Which is best iteration or recursion?
9Inserting an item into a BSTAlgorithm if
tree is empty, insert item at root if item is
less than item at current node, insert into left
sub-tree otherwise if item is greater than
item at current node, insert into right
sub-tree otherwise replace item at current
node with new value
10Implementation insert templatelt typename Key,
typename Value gtvoid insert( BNodelt Key, Value
gt root, const Key key, const
Value value )
11Implementation insert templatelt typename Key,
typename Value gtvoid insert( BNodelt Key, Value
gt root, const Key key,
Value value ) if (root NULL) root
makeNode(key, value) else if (key lt
root-gtkey) insert(root-gtleft, key, value)
else if (key gt root-gtkey)
insert(root-gtright, key, value) else
root-gtvalue value
12Exercise Insert the following keys (we wont
worry about the corresponding values) into an
empty binary search tree in the order given.
Note that in both cases, the data is the same but
the order in which we do the insertion is
different. Case 1 7, 4, 3, 6, 9, 8 Case 2 3,
4, 6, 7, 8, 9
13Note that in case 1, we end up with a bushy
tree, in fact, it is a complete binary tree. If
we were now to search for an item in this tree,
we could do it in O(log(N)) time. In case 2, our
tree is rather unbalanced or one-sided,
searching for an item in this tree would take
O(N) time. It is important to realize that our
insertion algorithm makes no attempt to balance
the tree it maintains only an ordering
property, not a shape property. It can be shown
that provided the data is inserted into the tree
in random order, the insertion can be performed
in O(log(N)) time on average.
14Removing an item from a BSTAlgorithm search
for the item to find the node containing the
item if the item was not found, were done
if the node is a leaf, delete the node if
the nodes left sub-tree is empty, replace node
with right child else if the nodes right
sub-tree is empty, replace node with left child
else replace node with its logical predecessor
(rightmost node of its left sub-tree) delete 5
from tree
15delete 7 from tree
delete 6 from tree
Note that by replacing the node with its logical
predecessor, we maintain the ordering property of
the binary tree. We can also replace the node
with its logical successor (left-most child of
right child).
16Exercise Complete the following
function templatelt typename Key, typename Value
gtvoid getPredecessor( BNodelt Key, Valuegt root,
Key key, Value value )// Pre root points
to the root of a BST and is not null // and
root-gtleft is not NULL// Post key and value are
the key/value pair of the// logical predecessor
of the BST pointed to by root
17Time complexity of BST operations If the binary
search tree is perfectly balanced so that the
number of levels is minimized, then search,
insert and remove operations can all be performed
in O(log N) time since the depth of the tree in
this case is O(log N). However, we have to
remember that our insert algorithm makes no
attempt to keep the tree balanced. In the worst
case, each of these operations degrades to O(N)
time making a BST no better for searching than a
linked list. It can be shown that on average
with random insertion, the depth of a binary
search tree (with no removals) is O(log N). If
we allow for removals, the tree can become
unbalanced because whenever we remove a node with
two child nodes, we end up removing the node
containing its logical predecessor and this is
always found in the left sub-tree.
18Implementing a Map using a BSTA binary search
tree can be used as the underlying data structure
for a map. We have seen that provided the tree
remains balanced, we can search, insert or remove
from the map in O(log N) time. We can also
access the smallest (or largest) item in O(log N)
time assuming that the tree is balanced.
19Retrieving the smallest item from a
BSTRetrieving either the smallest or largest
item from a BST is particularly easy because they
are stored in the extreme left and extreme right
nodes of the tree
20Implementation Retrieving the smallest item
from a BST
templatelt typename Key, typename Value gtvoid
findSmallest( BNodelt Key, Value gt root,
Key key, Value value )//Pre
root is not NULL//Post key/value correspond to
item with smallest key if (root-gtleft
NULL) key root-gtkey value
root-gtvalue else findSmallest
21A BST implementation of a map is also beneficial
if we want the data sorted by key value. Suppose
we want to print out the data to the screen
sorted by key value templatelt class Key, class
Value gtvoid printData( BNodelt Key, Value gt root
) This is an O(____) operation. What if
we were to implement our map using chained
hashing rather than a BST?