7.14.2. Binary Search

Searching is a task closely related to sorting. The basic idea is to quickly locate a specific value in an array or determine that the array doesn't contain the value. Although searching for a particular value in an array of simple data (e.g., characters or integers) has limited use, doing so is a good example of a searching algorithm. Searching for a specific element becomes more useful when the elements are objects, instances of structures, or classes.

Imagine that we begin with a student structure that has three fields or members: (1) the student's name, (2) the student's identification number, and (3) the student's GPA. Next, we create an array of objects instantiated from the structure and initialize all fields in each object. Now, we can search for a specific student's ID; if we find that ID, the search also returns the student's name and GPA. This operation is called an associative search, and the structure field used for the search, ID in this example, is called the key.

Binary search is a simple but effective searching algorithm often used with arrays. However, it has one requirement: we must sort the array before we can apply the binary search algorithm. The basic operation is to divide the array in half and ask, "Is the element I'm looking for in the top or bottom half?" Ignore the half of the array that doesn't contain the element, and then repeat the process until the algorithm locates the correct element or determines that the element is not in the array. The binary search doesn't change the array; instead, it performs its operations through three variables that index into the array.

A picture of a character array containing the sequence of characters SEETHEQUICKREDFOX Three variables, top, mid, and bottom, index into the array. top is at element C, mid is at I, and bottom is at X. After one iteration of the binary search algorithm, top is now at K, and mid is at R; bottom is unchanged at X. After the second iteration, top is still at K, but mid moves to O and bottom to Q. After the last iteration, top, mid, and bottom are all at Q.
(a)(b)(c)(d)(e)
Binary search. The binary search algorithm divides an array into two sub-arrays, determines if the key or target element is in the upper or lower sub-array, and then repeats. At some point, the sub-array is small enough that the key's location is determined or that the key is not in the array. The algorithm performs all partitioning steps (dividing the array into sub-arrays) through three index variables: Illustrated are the steps binary search takes to locate 'Q' (the key or target) in a simple array of characters:
  1. The original, unsorted array.
  2. The array is sorted, top and bottom are initialized, and the first value of mid is calculated.
  3. The key is in the bottom half of the array, so the algorithm updates top and calculates a new value for mid.
  4. The key is in the top half of the array, so the algorithm updates bottom and calculates a new value for mid.
  5. In this specific example, all three indexes are equal; it is not a requirement that top and bottom point to the key, only that mid does.

Binary Search: Simple Data

#include <iostream>
using namespace std;


void ssort(char* data, int size);
int  binsearch(char key, char* data, int size);


int main()
{
	char	data[] = { 'S','E','E','T','H','E','Q','U','I',		// (a)
			'C','K','R','E','D','F','O','X' };
	int	size = sizeof(data) / sizeof(char);			// (b)

	ssort(data, size);						// (c)

	int index = binsearch('Q', data, size);				// (d)

	if (index >= 0)							// (e)
		cout << "key found at index = " << index << endl;
	else
		cout << "key not in array" << endl;

	return 0;
}
A driver to test and demonstrate binary search.
  1. Test data
  2. The array size; NOTE: sizeof does NOT work with function arguments - that is, we can't calculate the size of the data array in the ssort function (see Figure 5)
  3. Call the selection sort function (see the previous section); binary search only works with sorted arrays
  4. Call binary search; the function returns the key's index in the array or -1 if the key is not in the array
  5. Testing the return value to determine what message to print
int binsearch(char key, char* data, int size)
{
	int top = 0;					// (a)
	int bottom = size - 1;				// (b)

	do						// (c)
	{
		int mid = (top + bottom) / 2;		// (d)
		if (key < data[mid])
			bottom = mid - 1;		// (e)
		else if (key > data[mid])
			top = mid + 1;			// (f)
		else
			return mid;			// (g)
	} while (top <= bottom);			// (h)

	return -1;					// (i)
}
A C++ implementation of binary search.
  1. Initialize the top index
  2. Initialize the bottom index
  3. Repeat until the function finds the key or determines that it isn't in the array
  4. Calculate an index in the middle of the sub-array
  5. If the key is in the top half of the sub-array, discard the bottom half
  6. If the key is in the bottom half of the sub-array, discard the top half
  7. If the key is located at the mid-point, return mid
  8. Binary search ends without finding the key when the top and bottom indexes cross
  9. Return -1 (an invalid array index) to denote that the key was not found

Binary Search: Objects

Review
#include <iostream>
using namespace std;

struct student
{	char	*name;
	int	id;
	double	gpa;
};

void ssort(student* data, int size);
int  binsearch(int key, student* data, int size);

int main()
{
	student students[] = {
			{ "Dilbert", 123, 3.5 },
			{ "Wally", 456, 2.0 },
			{ "Alice", 987, 3.9 },
			{ "Asok", 730, 3.8 },
			{ "Catbert", 501, 3.0 },
			{ "Pointy Haired Boss", 666, 1.0 },
			{ "Dogbert", 111, 4.0 }
		};
	int	size = sizeof(students) / sizeof(student);

	ssort(students, size);				// array must be sorted for binary search

	int index = binsearch(501, students, size);	// call binary search

	if (index >= 0)
		cout << "key found at index = " << index << endl;
	else
		cout << "key not in array" << endl;

	return 0;
}

int binsearch(int key, student* data, int size)
{
	int top = 0;
	int bottom = size - 1;

	do
	{
		int mid = (top + bottom) / 2;
		if (key < data[mid].id)
			bottom = mid - 1;		// search top half of sub-array
		else if (key > data[mid].id)
			top = mid + 1;			// search bottom half of sub-array
		else
			return mid;			// key found
	} while (top <= bottom);

	return -1;					// key not in the data array
}
Searching for objects based on one field. This version of the program searches in an array of objects instantiated from a structure. The example orders the array by the student's ID (see version 4 of the selection sort in the previous section). The program searches for the student with ID number 501.

Downloadable Code

ViewDownload
binsearch.cpp (simple data) binsearch.cpp (simple data)
binsearch2.cpp (object) binsearch2.cpp (object)