CS 261 – Fall 2009 Binary Search Trees
Can we do something useful? How can we make a collection using the idea of a binary tree? How about starting with an implementation of a BAG Goal: try to make the operations on the collection proportional to the length of a path, rather than the number of elements in the tree. First step. A Binary Search Tree.
Binary Search Tree Binary search trees are binary tree’s where every node’s object value is: –Greater than or equal to all its descendents in the left subtree –Less than or equal to all its descendents in the right subtree An in-order traversal will return the elements in sorted order If the tree is reasonably full, searching for an element is O(log n)
Binary Search Tree: Example AlexAbnerAngelaAdelaAliceAudreyAdamAgnesAllenArthurAbigail
Binary Search Tree (BST): Implementation struct BST { struct Node * root; int size; }; struct node { EleType value; struct node * left; struct node * right; }; void BSTinit (struct BST *tree); void BSTadd(struct BST *tree, EleType value); int BSTcontains (struct BST *tree, EleType value); void BSTremove (struct BST *tree, EleType value); int BSTsze (struct BST *tree);
Implementing the Bag: Contains Start at the root. At each node, compare to test: return true if match If test is less than node, look at left child Otherwise if test is greater than node, look at right child Traverses a path from the root to the leaf. Therefore, if the tree is reasonably complete (an important if) the execution time is O( ?? )
Implementing a Bag: Add Do the same type of traversal from root to leaf. When you find a null value, create a new node. AlexAbnerAngelaAdelaAliceAudreyAdamAgnesAllenArthurAbigail
A useful trick A useful trick (adapted from the functional programming world). Make a secondary routine that returns the tree with the value inserted. Node add (Node start, Object newValue) if start is null then return new Node with value otherwise if newValue < Node value left child = add (left child, newValue) else right child = add (right child, newValue) return current node
Add just calls the utility routine Class BST { … public void add (EleType newValue) { root = add(root, newValue); dataSize++; } … } What is the complexity? O( ?? )
Bag Implementation: Remove As is often the case, remove is the most complex. Leaves a “hole”. What value should fill the hole? AlexAbnerAngelaAdelaAliceAudreyAdamAgnesAllenArthurAbigail
Who can fill that hole? Answer: The Leftmost child of the right child. (Smallest element in right subtree) Try this on a few values. Useful to have a couple of private inner routines EleType leftmostChild (Node current) { … // return value of leftmost child of current } Struct Node * removeLeftmostChild (Node current) { … // return tree with leftmost child removed }
One additional special case We have said you want to fill hole with leftmost child of right child. What if you don’t have a right child? Think about it. Can just return left child. Try remove “Audrey” AngelaAliceAudreyAllenArthur
Remove: again easy if you return a tree Node remove (Node current, EleType testValue) if current->value is the thing we seek if right child is null return left child else replace value with leftmost child of right child and set right child to be removeLeftmost (right) else if testValue < current.value left child = remove (left child, testValue) else right child = remove (right child, testValue) return current node
What is the complexity?? Basically once more just running down a path from root to leaf What is the complexity? O(???) Careful! What can go wrong? What happens in the worst case?? Questions?? Now the worksheet.