Think of a number between 1 and 100. If I guess 50 and you say it is higher, I can stop considering every number below 51. I can do the same thing again with the remaining range.
That is the idea behind binary search. Try the game first, then step through the code to see how it keeps track of what is left.
Slide and guess. The shaded region shows where the number can be. Try to find it in seven guesses.
Choose a guess and see which numbers remain possible.
Follow the code
The code searches a sorted list of 15 numbers. lo and hi mark the remaining range. mid is the index in the middle.
At each step, the code compares the target with the middle value. If they differ, it removes the half that cannot contain the target. Pick a number and watch the highlighted line.
Choose a target from the list or tap a bar, then press Step to follow the code.
| lo | … |
| hi | … |
| mid | … |
| arr[mid] | … |
| target | 42 |
| midpoint checks | 0 |
| still possible | 15 books |
lo to mid + 1 removes the middle value and everything below it. Moving hi does the reverse. This list needs at most four midpoint checks. For the missing target, the loop ends when lo passes hi.
Try a much larger list
Halving makes the number of checks grow slowly. Doubling the list adds at most one more midpoint check. A sorted list of a billion items needs no more than 30.
The comparison below assumes each check takes one second so the difference is easy to see. It is not a timing benchmark.
Change the list size to compare the number of checks.
The list has to be sorted
The code can discard half the list because it knows which values are smaller or larger than the midpoint. That only works if the list is sorted.
Shuffle the numbers below. The target is still there, but the same code can now discard the part that contains it.
The number 23 is in this list. Shuffle the list and run the search. Check whether the result is correct.
What I would take from this
- Compare the target with the middle value, then narrow the remaining range.
- The number of midpoint checks grows logarithmically with the list size.
- An empty range means the target was not found, provided the list was sorted.
- Check that the data meets the algorithm's assumptions before trusting its result.
For one search through a small unsorted list, checking each item may be simpler. Sorting becomes more useful when you need to search the same data repeatedly.
About this example
The stepper computes a trace of the JavaScript shown. It counts midpoint checks, rather than individual JavaScript comparisons. The guessing game picks a random number. The shuffled example uses a fixed arrangement so the failure is repeatable. The one-second comparison shows operation counts, not measured runtime.