CSC153, Class 53: Binary Search Trees Overview: * Review (trees, binary search, dictionaries) * An ADT for binary search. * Binary search trees. * Using BSTs for dictionaries. Notes: * I hate deadlines. * Email me your extra credit. * Read my rant about end-of-course evaluations. * Fill out end-of-course evaluation (for Wednesday). * Exam 4 seems is not due today. Questions on the exam? * Sam rants about end-of-course evaluations. ---------------------------------------- Review: * What is a list (in the Scheme sense)? + Either null or cons of a value and null. * What is a tree (in the CS sense)? + A collection of elements in which each element is either a value or a number of pointers to elements. + Either a value or a collection of trees + A value plus a possibly-empty collection of trees * What is binary search? + An efficient technique for searching through ordered data structures pick middle element if it's what you're looking for stop otherwise, if it's smaller than what you're looking for recurse on the larger elements otherwise recurse on the smaller elements * What is a dictionary? + A data structure that holds values indexed by key objects --- Designing an ADT and data structure that supports binary search What operations does binary search require of its ADT? * Find the middle value * Look at the middle value * Extract elements larger than middle * Extract elements smaller than middle We can define an ADT that supports just these operations public interface BinarySearchable { public Object middle(); public BinarySearchable smaller(); public BinarySearchable larger(); public void add(Object obj); public void remove(Object obj); public boolean isEmpty(); } // interface BinarySearchable Standard implementation, sorted array: public class BinarySearchableArray implements BinarySearchable { Object[] contents; int lb; int ub; // Examples: // lb: 1, ub: 5, mid is 3 // lb: 0, ub: 4, mid is 2 // lb: 0, ub: 5, mid is 2 public Object middle() { return this.contents[(this.lb + this.ub)/2]; } // middle() public BinarySearchable smaller() { BinarySearchable result = new BinarySearchable(); result.lb = this.lb; result.ub = (this.lb+this.ub)/2 - 1; result.contents = this.contents; return result; } // smaller() } // class BinarySearchableArray Why not implement BinarySearchable with something like a heap? We'll use a tree that has: The middle element stored in the root Smaller elements stored in the left subtree Larger elements stored in the right subtree Each subtree having the same form This data structure is a Binary Search Tree [If you go on to take CSC301, you'll learn about 2-3 trees.] Adding to these trees is easy. Keep looking at each node and moving to smaller/larger subtree (as appropraite) until you run off the end. Add it there. Searching these trees is equally easy. If the tree is balanced (nearly complete or something similar), how long does add/find take? O(log_2(n)) Are all such trees balanced? Unfortunately, no. Can we keep them balanced? After we take CSC301 we can. Why use binary search trees rather than sorted arrays? O(log_2(n)) add vs. O(n) add. Why use binary search trees rather than hash tables? * Doesn't require a hash function. * But does require a may-precede. Why use lists rather than vectors? * Easier to add to The same holds for bsts vs. hash tables.