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.