Exponential search returns the first index of x, or NIL, with at most 2 floor(lg l) + 3 comparisons full
This proof shows: correctness, termination, complexity.
Let A[0…n−1] be sorted in non-decreasing order, n≥0, and let x be a key. Let ℓ=∣{j:A[j]<x}∣ be the lower bound of x. Because A is sorted, A[j]<x exactly for j<ℓ. The copies of x, if any, are at the indices ℓ,ℓ+1,…, so the answer is ℓ when ℓ<n and A[ℓ]=x, and NIL otherwise.
The doubling loop. Before each test of line L2:
- b=2k for an integer k≥0;
- A[j]<x for each j<⌊b/2⌋, that is, ⌊b/2⌋≤ℓ;
- b≤ℓ when b≥2, that is, the test at b/2 passed.
At the start b=1, ⌊b/2⌋=0, and statements 2 and 3 say nothing. A pass runs only when b≤n and A[b−1]<x, so b−1<ℓ and b≤ℓ. For the new value b′=2b we get ⌊b′/2⌋=b≤ℓ, which is statement 2, and statement 3 holds for b′ as well.
Termination. Each pass doubles b, and a pass runs only when b≤n, so there are at most ⌊lgn⌋+1 passes when n≥1, and none when n=0.
Exit. The loop stops when b>n or A[b−1]≥x. In the first case ℓ≤n. In the second case b≤n, and A[b−1]≥x gives ℓ≤b−1. In both cases ℓ≤min(b−1,n). Line L4 sets lo=⌊b/2⌋ and hi=min(b−1,n), so with statement 2,
lo≤ℓ≤hi. The binary search. Before each test of line L5, lo≤ℓ≤hi. A pass has lo<hi, so lo≤mid<hi. If A[mid]<x then mid<ℓ and the new lo=mid+1≤ℓ. Otherwise A[mid]≥x, so ℓ≤mid, and the new hi=mid≥ℓ. In both cases the invariant holds and hi−lo drops by at least 1, since the new size is ⌊(hi−lo)/2⌋ or ⌈(hi−lo)/2⌉−1. So the loop stops, with lo≥hi, and then lo=ℓ=hi.
Result. Line L9 runs with lo=ℓ and returns ℓ exactly when ℓ<n and A[ℓ]=x, which is the answer. Otherwise line L10 returns NIL, which is the answer. ■
The number of comparisons. If ℓ=0 and n≥1, the first test fails, lo=hi=0, and with line L9 there are 2 comparisons. If n=0 there are none.
Let ℓ≥1 and k=⌊lgℓ⌋, so 2k≤ℓ<2k+1. A test at b can pass only when b≤ℓ, by statement 3 for the next value, so the passes are at b=1,2,…,2j with j≤k, and there is at most one more test, a failing one. So the doubling makes at most k+2 tests, and it stops with b≤2k+1. The interval of line L4 then has s=hi−lo≤b−1−b/2=b/2−1≤2k−1 positions. The binary search makes at most ⌈lg(s+1)⌉≤k tests, because each test leaves at most ⌊s/2⌋ positions and ⌊(2k−1)/2⌋=2k−1−1. With the one test of line L9 the total is at most (k+2)+k+1=2⌊lgℓ⌋+3.