Binary Search Correctness Proof
Given a sorted array
int binary_search(int *a, int key, int n) {
int m, first = 0, last = n - 1;
while (first <= last) {
m = (first + (last - first / 2);
if (key > a[m]) {
first = m + 1;
} else if (key < a[m]) {
last = m - 1;
} else if (key == a[m]) {
return m;
}
}
return -1; // not found
}
Correctness Proof
This is just my attempt to prove that the binary search algorithm implemented above is correct. To prove binary search is correct, we want to prove the following:
- At every iteration binary search is still searching the correct range in the array. This can be achieved with a loop invariant.
- Binary search terminates.
If we are able to prove these two then we can conclude that binary search is correct.
Preconditions and Postconditions
In addition to loop invariants, we also need to describe the preconditions of binary search. Preconditions are just assertions that must be true at the beginning of our function. In our case, our precondition is that the array is sorted in an ascending order. If the array is not sorted, then we don’t guarantee anything about the outcome.
In addition to preconditions, we also need to describe our postconditions. Given that we met the preconditions, our loop invariant is correct and our algorithm terminates, our post condition is that we return -1 if the key is not in the array or return the index of the key in the array.
Loop Invariant Proof Requirements
As a reminder loop invariants have three parts that we need to prove: (from CLRS)
- The invariant is true before the first iteration of the loop. (Initialization)
- If the invariant is true before iteration
, then it is true before iteration . (Maintenance) - When the loop terminates, the invariant gives us a property to help show that the algorithm is correct. (Termination)
Binary Search's Loop Invariant
Let’s define the following loop invariant:
At the start of each iteration of the while loop above the following is true:
- If the key is in the array and so there is some
such that and then . This just means that we are correctly picking the right range to search at every iteration.
Initialization
Before the first iteration we know that
Maintenance
Suppose the invariant holds before iteration
(1)
(2)
(3)
From (1), (2), (3) we conclude that the invariant holds before iteration
Termination
Suppose we know we terminate (proof next), then by the loop invariant … [TODO]
Does Binary Search Terminate?
Will we terminate? we need to prove that if the search range is
Suppose
. We therefore, return and we are done (binary search terminates). . Our algorithm in this case searches the new range . We see here that . . Our algorithm will then search the new range . Similarly, we see here that .
From the three cases we conclude that binary search must terminate.
References
These are my study notes from CLRS.