The Binary Search Algorithm is a highly efficient method for finding a specific element within a sorted collection. It embodies the divide and conquer paradigm, dramatically reducing the search space in each step.
The core problem addressed by binary search is: given a sorted array a of elements and a target element x, determine if x is present in a. If x is found, its index (location) is returned; otherwise, a special value (like -1 or 0, depending on convention) indicates its absence.
This algorithm is a cornerstone in computer science due to its excellent performance characteristics for large datasets, provided the data is sorted.
Binary search is a classic application of the Divide and Conquer algorithmic paradigm. This paradigm involves three steps:
In binary search, the "divide" step is achieved by comparing the target with the middle element, which effectively splits the problem into searching in either the left or right half. The "conquer" step is the recursive application of binary search to the chosen half. The "combine" step is trivial, as finding the element in a subproblem is the solution to the original problem.
The algorithm operates by maintaining a search interval within the sorted array. It continuously narrows this interval until the target is found or the interval becomes empty.
Here's the step-by-step process:
low and high, initially pointing to the first and last elements of the array, respectively.mid index of the current search interval:
This formula helps prevent integer overflow compared to when and are very large.Let's illustrate with an example: Search for x = 33 in the array A = [8, 21, 34, 65, 72, 93, 95].
Array: [8] [21] [34] [65] [72] [93] [95]
Indices: 0 1 2 3 4 5 6
Target: 33
Step 1: Initial search space
low high
| |
[8] [21] [34] [65] [72] [93] [95]
0 1 2 3 4 5 6
Step 2: Calculate mid
low mid high
| | |
[8] [21] [34] [65] [72] [93] [95]
0 1 2 3 4 5 6
a[mid] = 65. Since 33 < 65, search left half. Update high = mid - 1.
Step 3: New search space
low high
| |
[8] [21] [34] [65] [72] [93] [95]
0 1 2 3 4 5 6
Step 4: Calculate mid
low mid high
| | |
[8] [21] [34] [65] [72] [93] [95]
0 1 2 3 4 5 6
a[mid] = 21. Since 33 > 21, search right half. Update low = mid + 1.
Step 5: New search space
low high
| |
[8] [21] [34] [65] [72] [93] [95]
0 1 2 3 4 5 6
Step 6: Calculate mid
low=mid=high
|
[8] [21] [34] [65] [72] [93] [95]
0 1 2 3 4 5 6
Binary search can be implemented iteratively using a while loop or recursively. The iterative approach is often preferred for its clear control flow and avoidance of recursion depth limits.
#include <vector>
#include <iostream>
#include <algorithm> // Required for std::sort if array is not pre-sorted
// Function to perform iterative binary search on a sorted vector
// Returns the index of the target if found, otherwise returns -1.
int binarySearchIterative(const std::vector<int>& arr, int target) {
int low = 0;
int high = arr.size() - 1; // Initialize high to the last valid index
// Continue as long as the search space is valid (low <= high)
while (low <= high) {
// Calculate mid index. Using this form prevents potential integer overflow
// that (low + high) / 2 could cause if low and high are very large.
int mid = low + (high - low)
The recursive approach naturally aligns with the divide and conquer paradigm. The function calls itself on smaller sub-arrays until a base case is met.
The general structure of a recursive binary search function BinSearch(a, low, high, x) would be:
low > high, the search space is empty. The element is not found, return -1.low == high (only one element left), check if a[low] == x. If yes, return low; else, return -1.mid = low + (high - low) / 2.a[mid] == x, return mid.x < a[mid], recursively call BinSearch(a, low, mid - 1, x).x > a[mid], recursively call BinSearch(a, mid + 1, high, x).This mirrors the iterative logic but uses the call stack to manage the search boundaries.
The efficiency of binary search comes from its ability to eliminate half of the remaining search space with each comparison.
Let be the time taken to search an array of size . At each step, we perform a constant number of operations (comparison, arithmetic) and then solve a subproblem of size approximately . This leads to the recurrence relation: where represents the constant time for comparison and index calculation.
Solving this recurrence relation reveals a logarithmic time complexity:
mid position.This makes binary search significantly faster than linear search () for large inputs. For instance, searching an array of one million elements () would take roughly 20 comparisons () with binary search, compared to up to one million comparisons with linear search.
Binary search is widely used in various computing contexts:
low, high, and mid pointers to narrow down the search interval.Binary search mandates that the data array or list must be sorted in non-decreasing order for it to function correctly.
The algorithm repeatedly divides the search space in half by comparing the target element with the middle element of the current sub-array.
At each step, a `mid` index is calculated to identify the central element, which serves as the pivot for partitioning the array.
Based on the comparison with the midpoint, either the left half or the right half of the array is efficiently eliminated from further consideration.
Due to the continuous halving of the search space, binary search achieves a significantly efficient time complexity, making it suitable for large datasets.
Test your understanding with 5 questions
What is the primary prerequisite for applying the Binary Search Algorithm to a collection of elements?
What is the worst-case time complexity of the Binary Search Algorithm for an array of $n$ elements?
During a binary search, if the target element $x$ is found to be less than the element at the `mid` index ($x < a[mid]$), what action should be taken next?
Consider a sorted array `A = [5, 12, 18, 25, 30, 45, 50]` and a target value `x = 25`. What is the sequence of `mid` indices (0-based) visited by a binary search algorithm?
Which of the following data structures is LEAST suitable for an efficient implementation of Binary Search due to its underlying access mechanism?
(low + high) / 2lowhighx with the element at a[mid]:
x == a[mid]: The target is found. Return mid.x < a[mid]: The target, if present, must be in the left half of the current interval. Update high = mid - 1.x > a[mid]: The target, if present, must be in the right half of the current interval. Update low = mid + 1.low > high (meaning the search interval is empty, and the target is not in the array) or the target is found.low > high6 Modules
6 Modules