data structures & algorithms binary search trees (bsts)

Post on 14-Dec-2015

225 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Data Structures & Algorithms

Binary Search Trees (BSTs)

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.

Can’t 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 sub-tree are less than the root’s key.◦ All items (keys) in the right sub-tree are greater than the root’s

key.◦ Each sub-tree 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 sub-tree are smaller than the value of the item in X.

The values of all items in its right sub-tree 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

Left RightKey

Left RightKey Left RightKey

Left RightKey

Key

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’.

6

2 8

1 4

3

6

2 8

1 4

3 7

A binary search tree

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 > 17b) 11 < 17c) 11 > 6d) 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 sub-tree, or all in the right sub-tree. It doesn’t 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

6

2 8 NULL NULL

1 NULL NULL 4 NULL

3 NULL NULL

t

Tree root node

5 NULL NULL

New Node

t

t

Inserting Item 5 to the Tree

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])

}

InOrder_Tree_Walk(x){

if x≠ NULL InOrder_Tree_Walk(left[x])

print key[x]InOrder_Tree_Walk(right[x])

}

4, 77, 16, 2020, 37, 3838, 43

BST-in-order-traverse (node)1. If node has left child

BST-in-order-traverse (Left(node))2. Apply operation to node (e.g. cout)3. If node has right child

BST-in-order-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-post-order-traverse (node)1. If node has left child

BST-post-order-traverse (Left(node))2. If node has right child

BST-post-order-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?

◦ We’re done

Is target < value at current node?◦ Yes: search left sub-tree◦ No: search right sub-tree

Search Starts from the Root

When given a pointer to the root of a tree and a key, Tree-Search 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 8

1 4

3

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 sub-tree, 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 sub-tree, then predecessor (x) is the lowest ancestor of x (above x on the path to the root) that has x in its right sub-tree.

• 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 z’s 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

15

5 20

18

40

45

removeElement(45)------------->

25

15

5 20

18

40

x occurs at a node with one child v: remove the nodecontaining x and make v a direct child of x’s parent (if any).

25

15

5 20

18

40

45

removeElement(20)------------->

25

15

5 18

40

45

x occurs at a node with two children: first replace x with smallest value in right sub-tree 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

15

5 20

18

40

45

removeElement(15)------------->

25

18

5 20

18

40

45

Now remove this<---

6

2 8

1 5

3

4

6

3 8

1 5

3

4Deletion of node 2.

before 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; } }

top related