C/C++ Arena

Step 2 of 6

Binary search

Looking for a word in a dictionary, you don't start at page 1. You open the middle, see whether your word comes before or after, and throw away the half it can't be in. After about 20 halvings, a million pages are down to one. That's binary search, and it only works on sorted data.

lo = 0, hi = n - 1
while lo <= hi:
    mid = lo + (hi - lo) / 2      (not (lo + hi) / 2: that can overflow!)
    if v[mid] == target: found
    if v[mid] < target: lo = mid + 1
    else: hi = mid - 1

Here it is on a sorted list of words, printing each step so you can watch the range shrink:

#include <iostream>
#include <string>
#include <vector>

int find_word(const std::vector<std::string>& words, const std::string& target) {
    int lo = 0, hi = (int)words.size() - 1;
    while (lo <= hi) {
        int mid = lo + (hi - lo) / 2;
        std::cout << "  look at [" << lo << ", " << hi << "] middle " << words[mid] << "\n";
        if (words[mid] == target) return mid;
        if (words[mid] < target) lo = mid + 1;    // target is to the right
        else hi = mid - 1;                        // target is to the left
    }
    return -1;
}

int main() {
    std::vector<std::string> w = {"ant", "bee", "cat", "dog", "eel", "fox", "gnu", "hen"};
    int fox = find_word(w, "fox");
    std::cout << "fox at " << fox << "\n";
    int cow = find_word(w, "cow");
    std::cout << "cow at " << cow << "\n";
}
  look at [0, 7] middle dog
  look at [4, 7] middle fox
fox at 5
  look at [0, 7] middle dog
  look at [0, 2] middle bee
  look at [2, 2] middle cat
cow at -1

Why it's fast

Each step halves the range: 8, 4, 2, 1. A million elements need at most 20 steps, a billion about 30. That's O(log n).

The details that matter

Binary search is famously easy to get subtly wrong. Write it carefully once and understand every + 1 and - 1.

Your turn: write int find_index(const std::vector<int>& v, int target) returning the index of target in the sorted vector v, or -1. Don't use the standard library's search functions.

Previous: Big-O in practice Next: lower_bound and upper_bound