|
| 1 | +""" |
| 2 | +Binary search algorithm, iterative implementation. |
| 3 | + |
| 4 | +A binary search is a method to quickly find a given item in a sorted |
| 5 | +list. It's important the input list is sorted, or the binary search |
| 6 | +algorithm won't be useful at all. Sorted lists are things like |
| 7 | +alphabets (because "A" is always before "B," and so on), or number |
| 8 | +lines (because "1" is always before "2," and so on). |
| 9 | +""" |
| 10 | + |
| 11 | +def binary_search_iterative(stuff, item): |
| 12 | + """ |
| 13 | + Return the index of ``item`` in ``list`` using binary search. |
| 14 | + |
| 15 | + Args: |
| 16 | + stuff (list): A Python list that has already been sorted. |
| 17 | + item: The value of the item to search for (not its index). |
| 18 | + |
| 19 | + Returns: |
| 20 | + The index of ``item`` or ``None`` if ``item`` is not found. |
| 21 | + |
| 22 | + >>> binary_search_iterative([1, 2, 3, 4, 5, 6, 7, 8], 8) |
| 23 | + Guess number 1 is 4 |
| 24 | + Guess number 2 is 6 |
| 25 | + Guess number 3 is 7 |
| 26 | + Guess number 4 is 8 |
| 27 | + 7 |
| 28 | + |
| 29 | + Notice that the final return value is 7, not 8, because Python |
| 30 | + list indexes start counting from position number 0, not number 1. |
| 31 | + """ |
| 32 | + |
| 33 | + # We will be keeping track of a range of positions instead of |
| 34 | + # looking at position 0 and then looking at position 1, so we need |
| 35 | + # to keep track of the lowest and highest positions of that range, |
| 36 | + # not just the current spot in the list of stuff we're looking at. |
| 37 | + |
| 38 | + # The low position always starts at 0. |
| 39 | + low = 0 |
| 40 | + |
| 41 | + # The high position is however much stuff we're looking through. |
| 42 | + high = len(stuff) - 1 |
| 43 | + |
| 44 | + # We also keep track of how many guesses we're making to find it. |
| 45 | + guess_number = 0 # (This is just for our own edification.) |
| 46 | + |
| 47 | + # Eventually, `low` and `high` will converge, because we'll keep |
| 48 | + # shrinking the range by half (hence, "*binary* search") until we |
| 49 | + # find the item we're looking for. After each guess, we'll loop |
| 50 | + # (that is, we'll iterate) over the same list in a narrower range. |
| 51 | + while low <= high: |
| 52 | + # The middle spot of our range is always going to be the |
| 53 | + # current value of low plus high, divided by two. |
| 54 | + mid = (low + high) / 2 |
| 55 | + |
| 56 | + guess = stuff[mid] # That middle spot will be our next guess, |
| 57 | + guess_number = guess_number + 1 # so let's count our guesses. |
| 58 | + |
| 59 | + # How many guesses have we made so far? |
| 60 | + print("Guess number " + str(guess_number) + " is " + str(guess)) |
| 61 | + |
| 62 | + if guess == item: # If this is the correct guess, |
| 63 | + return mid # then we've found the item! Yay! :) |
| 64 | + |
| 65 | + # If we haven't found the item yet, then our guess was either |
| 66 | + # too low or too high. Thankfully, our list of stuff is sorted |
| 67 | + # so, if the guess was too high |
| 68 | + if guess > item: |
| 69 | + # then we know the item we're looking for is in the lower |
| 70 | + # half of our range. This means we can set the high end of |
| 71 | + # our range to the middle position of our last guess. We |
| 72 | + # also subtract 1 since we know our last guess was wrong. |
| 73 | + high = mid - 1 |
| 74 | + else: |
| 75 | + # On the other hand, if the guess was too low, then we |
| 76 | + # know the item is in the higher half of our range, so we |
| 77 | + # set the low end of our range to the middle position of |
| 78 | + # our last guess, instead. |
| 79 | + low = mid + 1 |
| 80 | + |
| 81 | + # If we still haven't found the item, then it's not in the list! |
| 82 | + return None |
| 83 | + |
| 84 | +if __name__ == "__main__": |
| 85 | + num = int(raw_input('Enter a number between 1 and 100: ')) |
| 86 | + binary_search_iterative(range(1, 101), num) |
0 commit comments