Sie sind auf Seite 1von 39

Binary Search Trees

When we store ordered data in an array, we


have a very efficient search algorithm, the
binary search.
However, we have very inefficient insertion
and deletion algorithms that require shifting
data in the array.

To provide for efficient insertions and


deletions, we developed the linked list.
The problem with linked lists, however, is
that their search algorithms are sequential
searches, which are very inefficient.
Cant we get the best of both worlds (i.e.,
efficient search, insertion, and deletion
algorithms)?

The binary search tree is our answer!


The binary search tree is a binary tree with
the following properties:

All items (keys) in the left subtree are less than


the roots key.
All items (keys) in the right subtree are greater
than the roots key.
Each subtree is, itself, a binary search tree.

Assume each node of a binary tree stores a data


item
Assume data items are of some type that be
ordered and all items are distinct. No two items
have the same value.

A binary search tree is a binary tree


such that
for every node X in the tree:
the values of all the items in its left subtree are
smaller than the value of the item in X
the values of all items in its right subtree are
greater than the value of the item in X.

Here you can


see the basic
structure of a
binary search
tree.

A binary search tree is organized as the


name suggests
A tree can be represented by a linked data
structure where each node is an object
In addition to a key field, each node
contains fields left, and right, that
correspond to its left child and right child

Key
Key Left
Left Right
Right

Key
Key Left Right

Key

Left Right

If a child or parent is missing, the appropriate


field contains the value NULL.

The root is only node in the tree, whose parent


field is NULL.

Top of the tree is known as root and the


exposed nodes at bottom are known as leafs.

A binary search tree


6
2
1

8
4

6
2
1

8
4

Not a binary search tree,


but a binary tree

- a & b are full and BST


-a, b, & d are complete
-c and e are skewed

Here we see examples of


binary trees that are not
binary search trees why?

a) 22 > 17
b) 11 < 17
c) 11 > 6
d) 22 > 17

Note: we have written this definition in a way


that ensures that no two entries in a binary
search tree can have equal keys.

Although it is possible to modify the definition


to allow entries with duplicate keys, it makes
the algorithms somewhat more complicated.

If duplicates need to be accounted for, they


can be stored in another data structure (e.g.,
list).

The search tree property does not say what happens with
the elements with the same key. In our examples, all the
keys will be distinct but in practice it is important to cover
the case of multiple elements with the same key (duplicate
keys).
The duplicate keys can all be kept in the left subtree, or all
in the right subtree. It doesnt matter which we choose, but
it matters that the choice is the same for the whole
implementation.
Another issue: with duplicate keys, it is important to have
extra operations in the interface: getAll, and removeAll

Binary trees offer short paths from root


A node has up to two children
Data is organized by value
Operations:

Insertion
Search
Traversal
Deletion

Find Minimum

Find the item that has the minimum value in the tree

Find Maximum

Find the item that has the maximum value in the


tree

Print

Print the values of all items in the tree using a


traversal strategy that is appropriate for the
application

Successor

Predecessor

The first value inserted goes at the root


Every node inserted becomes a leaf
Descend left or right depending on value

Inserting Item 5 to the Tree


t
Tree root node

t
2

NULL

NULL

NULL

NULL

t
1

NULL

NULL

NULL

NULL

NULL

New Node

The BST property allows us to print out all


keys in BST in sorted order using a simple
recursive algorithm.

InOrder_Tree_Walk(x)
{
if x NULL
InOrder_Tree_Walk(left[x])
print key[x]
InOrder_Tree_Walk(right[x])
}

4, 7, 16, 20, 37, 38, 43

BST-inorder-traverse (node)
1. If node has left child
BST-inorder-traverse (Left(node))
2. Apply operation to node (e.g. cout)
3. If node has right child
BST-inorder-traverse (Right(node))
Order for tree above: 1, 2, 3, 5, 6, 7
Application: Display tree in ascending
order

BST-preorder-traverse (node)
1. Apply operation to node e.g cout
2. If node has left child
BST-preorder-traverse (Left(node))
3. If node has right child
BST-preorder-traverse (Right(node))

Order for tree above: 3, 1, 2, 6, 5, 7


Application: Copy BST

BST-postorder-traverse (node)
1. If node has left child
BST-postorder-traverse (Left(node))
2. If node has right child
BST-postorder-traverse (Right(node))
3. Apply operation to node e.g cout
Order for tree above: 2, 1, 5, 7, 6, 3
Application: Deallocate BST

Want to search for key stored in BST


Functions:
Tree search
Minimum
Maximum
Successor
Predecessor

Start at the root


Is target = value at current node?

Were done

Is target < value at current node?


Yes: search left subtree
No: search right subtree

Search Starts from the Root

When given a pointer to the root of a tree and a key, TreeSearch will return a pointer to the node with key k if one exists
(x = root).

Tree-Search (x, k)
{
if x=NULL or k=key[ x]
return x
if k<key [x]
return Tree-Search( left[ x], k)
else
return Tree-Search( right[ x], k)
}

This function follows the BST property, if


value of k is smaller than that of x, then it
should be in left sub tree of x, else it
should be in right sub tree of x.
6
2
1

8
4

The minimum element of BST is the left


most node of left sub tree.

Therefore the minimum can always be found


by tracking the left child pointers until an
empty sub tree is reached.

If there is no left sub tree then minimum key


is at root( i.e. key[ x])
Tree-Minimum(x)
{
while( left[ x] != NULL)
x = left [x]
return x
}

The maximum element of BST is the right most


node of right sub tree.

Therefore the maximum can always be found by


tracking the right child pointers until an empty sub
tree is reached.
Tree-Maximum( x)
{
while( right[ x] != NULL)
x = right [x]
return x
}

The successor of a node x, is node y, that has


the smallest key greater than that of x.
If x has a right subtree, then successor(x) is the
left most element in that sub tree.
If x has no right sub tree, then successor(x) is the
lowest ancestor of x (above x on the path to the
root) that has x in its left sub tree.

The successor of node with key 15 is node with key 17.


The successor of node with key 7 is node with key 9.
The successor of node with key 13 is node with key 15.

The predecessor is the node that has the


largest key smaller than that of x
If x has a left sub tree, then the predecessor must
be the right most element of the left sub tree.
If x has no left subtree, then predecessor (x) is
the lowest ancestor of x (above x on the path to
the root) that has x in its right subtree.

The predecessor of node with key 6 is node with key 4.


The predecessor of node with key 15 is node with key 13.
The predecessor of node with key 17 is node with key 15.

If z has no children, we modify its parent to


replace z with NULL as child.

If z has one child, we splice out z by making


a new link between its child and its parent.

If node has two children, we splice out zs


successor y, which has no left child and
replace the contents of z with the contents
of y.

Three cases for remove(x):


x occurs at a leaf: simply remove the node containing x
25
40

15
5

20
18

25

45

40

15
removeElement(45)

------------->

20
18

x occurs at a node with one child v: remove the node


containing x and make v a direct child of xs parent (if any).
25
40

15
5

20

45

18
removeElement(20)

------------->
5

25
40

15
18

45

x occurs at a node with two children: first replace x with


smallest value in right subtree of x. This value occurs at a
node with no left child. So we can delete this node using
one of the two previous cases.
25
40

15
5

20

45

25
40

18

18
removeElement(15)

------------->

20
18

45

<--- Now remove this

6
2
1

8
5

8
5

3
4

before

Deletion of node 2.

4
after

template <class Comparable>


void BinarySearchTree<Comparable>::
remove( const Comparable & x,
BinaryNode<Comparable> * & t ) const
{
if( t == NULL )
return; // Item not found; do nothing
if( x < t->element )
remove( x, t->left );
else if( t->element < x )
remove( x, t->right );
else if( t->left != NULL && t->right != NULL ) // Two children
{
t->element = findMin( t->right )->element;
remove( t->element, t->right );
}
else
{
BinaryNode<Comparable> *oldNode = t;
t = ( t->left != NULL ) ? t->left : t->right;
delete oldNode;
}
}

Das könnte Ihnen auch gefallen