Binary search is an improvement over linear searching that works only if the data in the array are sorted beforehand.
Suppose we have the following array data shown under the array indices:
10 20 30 40 50 60 70 80 90 100 115 125 135 145 155 178 198
Binary search works by keeping track of the midpoint (mid) and the minimum (min) and maximum (max) index positions where the item might be.
If we are looking for a number, say, 115, here is a visual on how we might go about it. We display the indices over the data being considered. Here min and max are the smallest and largest index to still consider. A textual explanation follows the visual:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
10 20 30 40 50 60 70 80 90 100 115 125 135 145 155 178 198
min=0 max=16 mid=8
100 115 125 135 145 155 178 198
min=9 max=16 mid=12
100 115 125
min=9 max=11 mid=10
Item 115 found at position 10
So binary search (as its name might suggest) works by dividing the interval to be searched during each pass in half. If you think about how it’s working here with 17 items. Because there is integer division here, the interval will not always be precisely half. it is the floor of dividing by 2 (integer division, that is).
With the data above, you see that the algorithm determined the item within 3 steps. To reduce to one element to consider, it could be 4 or 5 steps. Note that \(4 < log_2 17 < 5\).
Now that we’ve seen how the method works, here is the code in binary_searching/binary_searching.cs that does the work:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /// Return the index of item in a non-empty sorted array data,
/// or return -1 if item is not in the array.
public static int IntArrayBinarySearch(int[] data, int item)
{
int min = 0, max = data.Length-1;
while(min <= max) {
int mid = (min+max) / 2;
if (data[mid] == item)
return mid;
if (item > data[mid])
min = mid + 1;
else
max = mid - 1;
}
return -1;
}
|
Here’s a quick explanation, because it largely follows from the above explanation.
min <= max
).data.Length - 1
.Of course we generally would be searching in an array with multiple elements. It is still important to check edge cases: Check that the code correctly returns -1 if the array has length 0 (a legal length).
Similar to linear searching, we provide a main program that tests it out. in binary_searching/binary_searching_demo.cs. It uses an elaboration of binary search that prints out the steps visually, as in the introduction to this section. It also references previous example projects: functions from files searching/extract_from_string.cs and sorting/sorting.cs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | string input = UI.PromptLine(
"Please enter some comma/space separated integers: ");
int[] data = ExtractFromString.IntsFromString(input);
Sorting.IntArrayShellSortBetter(data);
string prompt =
"Please enter a number to find (empty line to end): ";
input = UI.PromptLine(prompt);
while (input.Length != 0) {
int searchItem = int.Parse(input);
int foundPos = BinarySearching.IntArrayBinarySearchPrinted(
data, searchItem);
if (foundPos < 0)
Console.WriteLine("Item {0} not found", searchItem);
else
Console.WriteLine("Item {0} found at position {1}",
searchItem, foundPos);
input = UI.PromptLine(prompt);
}
|
Even if you do not find item
in a binary search, it is sometimes useful to know
where item
lies in relation to the array elements. It could be
before the first element, in between two elements, or after the last element.
Suppose N
is the (positive) array length.
Instead of just returning -1 if item
is not in the array, return
item < data[0]
-(k+1)
if data[k-1] < item < data[k]
-(N+1)
if data[N-1] < item
Modify binary_searching/binary_searching.cs into
binary_searching2.cs
so this extra information is returned
(and indicated clearly in a main testing program derived from
binary_searching/binary_searching_demo.cs).
This should not require a change to the while
loop, nor
require any added loop.