# Class 50: Binary Search Trees

Back to Dictionaries. On to Hash Tables.

Held Tuesday, November 28, 2000

Summary

Today we consider one interesting implementation of dictionaries: search trees. As the name suggests, search trees are trees that are designed to help you search for elements.

Notes

• Are there any questions on exam 3?
• Update on search.
• I'm still thinking about the final assignment. Do you really want another assignment?
• Form of the final (in-class).
• No class Friday.

Overview

• Review: Trees, Dictionaries, and More
• Idea: Apply trees to problem of searching
• Binary search trees: Basic design
• An alternative perspective: "binary searchable objects"

## Review

• What is a tree?
• Are there natural ways to order things?
• How do we search for large and small values in a collection?
• What is a dictionary?

## Search Trees

• Another strategy for building dictionaries is to use search trees. Search trees use the basic idea of binary search, but encapsulate it in a particular way.
• As in the case of heaps, search trees apply the divide-and-conquer approach to the design of data structures.
• Can we also represent such structures as linked objects, using nodes?
• Yes, we'll give each node two links: one to a tree of smaller things and one to a tree of larger things.
• For example, we might build the following structure for the first seven letters of the alphabet.
```      D
/   \
B     F
/ \   / \
A   C E   G
```
• Similarly, here's a structure for the names of some faculty members.
```              Rebelsky
/        \
Ferguson    Walker
/     \       /    \
Chamberland  Herman Stone Wolf
/         /   \
/    \
Hill  MooreE
\
MooreT
```
• Such structures are called binary search trees
• Binary: there are no more than two child links per node.
• Search: you use them for looking for things.
• Trees: They look somewhat like upside-down trees .
• How do we use search trees? The same way we use binary search.
• To find an element in a search tree, you compare the object you're looking for to the current node. If the object you're looking for is smaller, you follow the left branch. If the object you're looking for is bigger, choose the right branch.
• We can use a similar process to insert an element.
• You look at the current node.
• If the node is empty, you build a new node.
• If the node contains the appropriate key, you replace it.
• If the value to be inserted is larger, you recurse on the right subtree.
• If the value to be inserted is smaller, you recurse on the left subtree.
• If we can keep the tree relatively balanced, this gives an O(log2n) algorithm.
• Unfortunately, keeping the tree balanced is difficult. Balancing trees is a topic for CSC301.
• In order to implement `Dictionary` with binary search trees, we'll build a wrapper class. This class will permit us to
• Represent empty collections.
• Keep track of the `Comparator` used to determine large and small.

## Another Perspective: Binary Search Trees for Binary Search

• We can also think about the structure by revisiting binary search.
• We've used binary search on arrays, but are there other structures we can use it on? We might answer this by considering the operations binary search requires (and, therefore, the data structure specification).
• What operations do we need to do binary search?
• Grab the ``middle'' element.
• Grab the ``smaller'' elements: everything less than the ``middle'' element.
• Grab the ``larger'' elements: everything greater than the ``middle'' element.
• We might build a data structure (or at least an interface) that directly supports those three operations.
```public interface BinarySearchable
{
/**
* Get the ``middle'' key in the collection.
* Pre: The collection is nonempty.
* Post: Returns some designated element in the collection.
*/
public Object middle();

/**
* Get elements in the collection that are smaller than the
* middle element.
* Pre: The collection is nonempty.
* Pre: The collection has not been modified since the last call
*   to middle.
* Post: Returns the smaller elements.
*/
public BinarySearchable smaller();

/**
* Get elements in the collection that are larger than the
* middle element.
* Pre: The collection is nonempty.
* Pre: The collection has not been modified since the last call
*   to middle.
* Post: Returns the larger elements.
*/
public BinarySearchable larger();

/**
* Determine if the collection is empty.
*/
public boolean isEmpty();
} // BinarySearchable
```
• Rephrasing binary search in terms of these operations,
```  public boolean binarySearch(BinarySearchable stuff,
Object findMe,
Comparator order)
{
if (stuff.isEmpty())
return false;
int compareVal = order.compare(findMe, stuff.middle());
if (compareVal == 0)
return true;
else if (compareVal < 0)
return binarySearch(stuff.smaller(), findMe, compare);
else ; if (compareVal > 0)
return binarySearch(stuff.larger(), findMe, compare);
} // binarySearch(BinarySearchable, Object, Comparator)
```
• We already know how to implement such structures using sorted arrays. An advantage of sorted arrays is that all the operations are O(log2n) (as long as we're cautious about how we represent these structures).
• Binary search trees can provide another O(log2n) algorithm.

## History

Wednesday, 23 August 2000

• Created as a blank outline.

Thursday, 24 August 2000

• Slight reorganization to page design.

Tuesday, 28 November 2000

Back to Dictionaries. On to Hash Tables.

Disclaimer Often, these pages were created "on the fly" with little, if any, proofreading. Any or all of the information on the pages may be incorrect. Please contact me if you notice errors.