# Class 24: Binary Search

Back to Project Discussion. On to Sorting Algorithms.

Held Wednesday, October 6, 1999

Overview

Today, we'll consider the joys of binary search, an important divide and conquer algorithm. We will also consider some underlying object-oriented design issues for comparing objects.

Notes

• I've updated Monday's outline to include the narrative we developed.
• A few of you who did not participate in yesterday's discussion seemed to have missed the key points:
• Each team needs to think closely about what related classes their classes will use.
• Each team needs to think closely about how others will use their classes.
• Each team will need to carefully document what their classes can do (but not how they will do those things).
• I'll do my best to involve other teams in the next discussion (which may take off where we left off).
• Mr. Walker will continue to visit this week.
• This coming weekend is parents' weekend. Please let me know soon if you intend to bring your parents to class on Friday.
• Are there any questions on assignment 3?
• I've received some requests to make the course outlines available earlier. I'll do my best, but it's often best for me to wait until the last minute.
• You may want to do lab A2.5 to further ground your understanding of this material.

Contents

Handouts

• Selections from Chapter 12 of Java Plus Data Structures

Summary

• Binary Search
• Iterative vs. recursive
• In Scheme
• In Java
• Examples
• Comparing objects
• Assigned: Selections from Chapter 12 of Java Plus Data Strucures

## Binary Search

• You've seen binary search in CSC151, so some of this may be review.
• Binary search is one of the ``classic'' algorithms.
• It takes advantage of the design technique known as divide and conquer
• To solve a big problem, divide it into smaller parts and solve the parts.
• Like many divide and conquer algorithms, binary search is typically expressed recursively.
• However, it may also be expressed iteratively.
• To search for element e in sorted array A, search for e in the subrange of A from 0 to (last index in A).
• To search for element e in subrange l to u of A,
• Identify a midpoint, m
• If e is at the midpoint, return the appropriate information.
• If e is smaller than the value at the midpoint, throw away the upper half of the array (reduce the subrange).
• If e is greater than the value at the midpoint, throw away the lower half of the array (reduce the subrange).
• We'll do an example that has to do with phone books (if I can find my phone book).

### Recursive and Iterative Formulations

• Here's a recursive formulation
```boolean binarySearch(Element element, Collection stuff)
If stuff is empty then return false
Identify mid, the middle element of stuff
If element equals mid then
Return true
Else if element < mid then
Let smaller be the elements of stuff smaller than mid
Return binarySearch(element, smaller)
Else // element > mid
Let bigger be the elements of stuff larger than mid
Return binarySearch(element, bigger)
```
• Here's an itereative formulation
```boolean binarySearch(Element element, Collection stuff)
While there are usable elements in stuff
Identify mid, the middle usable element
If element equals mid then
Return true
Else if element < mid then
Mark all elements greater than mid as unusable
Else
Mark all elements less than mid as unusable
```

### Running Time

• So, what's the running time of this algorithm?
• It may depend on how you mark or extract the larger or smaller elements.
• If you need to look at all the elements to mark them as larger or smaller, this is clearly an inefficient formulation.
• Hence we need to organize the elements in such a way that ``extract the smaller/larger elements'' or ``mark the smaller/larger elements as unusable'' are O(1) operations.
• A typical strategy is to organize the elements into a sorted array. By keeping track of the upper and lower bounds of a subarray of elements left to look at, we can make that an O(1) algorithm.
• lb is the index of the smallest element in the subarray
• ub is the index of the largest element in the subarray

#### Using an Array

• Here's a recursive formulation, using a sorted array. Instead of returning a boolean value, we'll return the index of the element.
```int binarySearch(Element element, Element[] stuff)
return binarySearch(element, stuff, 0, stuff.length-1)
int binarySearch(Element element, Element[] stuff, int lb, int ub)
If stuff is empty then return false
mid = stuff[(lb+ub)/2];
If element equals mid then
Return (lb+ub)/2];
Else if element < mid then
Return binarySearch(element, stuff, lb, (lb+ub)/2 - 1);
Else
Return binarySearch(element, stuff, (lb+ub)/2 + 1, ub);
```
• How do we code one of these versions in Scheme?
• How might we code both versions in Java?

## Comparing Elements

• All is well and good when we want to search arrays of integers or other things that we can compare with < and >, but what if we want to sort arrays of objects?
• There are two basic possibilities:
• We can create objects that compare themselves to other objects.
• We can create objects that compare pairs of objects.
• We might call the first kind of objects `Comparable`s and the second `Comparator`s.
• Here's a possible interface for `Comparable` objects.
```
import IncomparableException;

/**
* Objects that can be compared to each other.  Particularly
* useful for objects that must be sorted or searched.  Assumes
* that comparison is transitive and that if a < b then b > a.
*
* @author Samuel A. Rebelsky
* @version 1.0 of October 1999
*/
public interface Comparable {
/**
* Determine if this object should precede another object.
*
* @exception IncomparableException
*   If such comparison is not possible, such as when you
*   try to compare apples to oranges.
*/
public boolean lessThan(Object other)
throws IncomparableException;

/**
* Determine if this object is the same as another object.
*
* @exception IncomparableException
*   If such comparison is not possible, such as when you
*   try to compare oranges to apples.
*/
public boolean equals(Object other)
throws IncomparableException;
} // interface Comparable

```
• Here's a possible interface for `Comparator` objects.
```
/**
* Objects that can compare pairs of objects (for equality and
* ordering).  We assume that if something is neither less than
* or equal to another object, then it is greater than that other
* object.  Typically used to help with sorting.
*
* @author Samuel A. Rebelsky
* @version 1.1 of October 1999
*/
public interface Comparator {
/**
* Determine if the first element is strictly smaller than the
* second.   Throws an exception if the two elements cannot
* be compared.
*/
public boolean lessThan(Object first, Object second)
throws IncomparableException;

/**
* Determine if the first element is equal to the second.   Throws
* an exception if the two elements cannot be compared.
*/
public boolean equals(Object first, Object second)
throws IncomparableException;

} // interface Comparator

```
• Here's one implementation of `Comparator`.
```
import Comparator;

/**
* Compares two objects by considering their string representations.
* Does case-insensitive comparision.  Particularly useful for
* comparing strings, but can also be used for other objects.
*
* @author Samuel A. Rebelsky
* @version 1.1 of October 1999
*/
public class StringComparator
implements Comparator
{
/**
* Determines if the string reperesentation of the first object
* is the same as the string representation of the second object.
* Pre: The two objects are initialized and can be converted to strings.
* Post: Returns true if they are equal and false otherwise.
*/
public boolean equals(Object first, Object second)
{
String firstString = first.toString().toLowerCase();
String secondString = second.toString().toLowerCase();
return firstString.equals(secondString);
} // equals(Object,Object)

/* Determines if the string representation of the first object
* is less than the string representation of the second object.
* One string is "less than" another iff letters 0 through i-1
* of the two strings are the same and either (i) letter i of the
* first string is less than letter i of the second string or (ii)
* the first string has only i letters and the second string has more
* than i letters.
*/
public boolean lessThan(Object first, Object second)
{
String firstString = first.toString().toLowerCase();
String secondString = second.toString().toLowerCase();
// The compareTo operator returns a negative value if
// the first string precedes the second.
return firstString.compareTo(secondString) < 0;
} // lessThan(Object,Object)
} // class StringComparator

```
• Think about how else you might implement these classes.

## History

Tuesday, 10 August 1999

• Created as a blank outline.

Friday, 1 October 1999

• Filled in some details.

Tuesday, 5 October 1999

• Filled in many more details.
• Added the section on `Comparable`s and `Comparator`s.

Wednesday, 6 October 1999

• A few minor corrections.

Back to Project Discussion. On to Sorting Algorithms.

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.