Search code examples
cbinary-search

How to keep track of the last index in a binary search algorithm?


I am solving a simple binary search algorithm but I am not able to keep track of the last index in the question.

Although, I have tried and included a counter but in vain as it does not give me the expected output.

  void binarySearch(int Arr[], int Size, int Search)
   {
    int Flag=0, Counter=1, First=0, Last=Size-1, Mid;
   while(First<=Last)
      {
       Mid=(First+Last)/2;
       printf("\nGuess %d (half of %d to %d) -> ", Arr[Mid], First, 
             (Last+Counter));
           if(Arr[Mid]==Search)
              {
                  printf("spot on!");
                  Flag=1;
                   break;
             }
           else if(Arr[Mid]<Search)
             {
                printf("you're too low.");
                First=Mid+1;
             }
           else
             {
                 ++Counter;
                 printf("you're too high.");
                 Last=Mid-1;
             }
      }
   if(Flag==0)
      printf("\nElement Not Found!!");
 printf("\n");
}

Expected Output:-

Say my chosen number is 38. What are you going to do? Do a binary search:

Guess 50 (half of 0 to 100) → you’re too high.

Guess 25 (half of 0 to 50) → you’re too low.

Guess 37 (half of 25 to 50) → you’re too low.

Guess 43 (half of 37 to 50) → you’re too high.

Guess 40 (half of 37 to 43) → you’re too high.

Guess 38 (half of 37 to 40) → spot on!

Actual Output:-

Guess 50 (half of 0 to 100) -> you're too high.

Guess 25 (half of 0 to 50) -> you're too low.

Guess 37 (half of 25 to 50) -> you're too low.

Guess 43 (half of 37 to 50) -> you're too high.

//Here is my doubt

Guess 40 (half of 37 to 44) -> you're too high.

Guess 38 (half of 37 to 42) -> spot on!


Solution

  • The trick with efficient binary searches is that you check the very first and very last element in the array first.

    Obviously, if the value you search for is outside, there is no need to do a binary search; and if either end matches, you have found it.

    However, then it means that the boundaries for the binary search are exclusive. When you calculate the index for the next element to be probed, if it matches one of the boundaries, you know there is no match.

    In pseudocode, this means we can write the binary search, assuming a sorted array with values in increasing values, and indexing starting at 0 as in C, as

    Function BinarySearch(array[], length, value):
    
        If (length < 1):
            # Empty array.
            Return NotFound
        End If
    
        If (value < array[0]):
            # Value is smaller than those in the array.
            Return NotFound
        Else If (value == array[0]):
            Return Found at index 0
        End If
    
        If (value > array[length - 1]):
            # Value is greater than those in the array.
            Return NotFound
        Else If (value == array[length - 1]):
            Return Found at index length - 1
        End If
    
        Let  iMin = 0
        Let  iMax = length - 1
        Loop:
    
            Let  i = (iMin + iMax) / 2   # Integer division, rounds towards zero
            If (i == iMin):
                Return NotFound
            End If
    
            If (array[i] < value):
                iMin = i
            Else If (array[i] > value):
                iMax = i
            Else:
                Return Found at index i
            End If
        End Loop
    End Function
    

    When integer division is used, and iMin and iMax are nonnegative (positive or zero), i = (iMin + iMax)/2 rounds towards zero, and i == iMin occurs first, so we do not need to explicitly check for i == iMax. (That is, i == iMax occurs in this case only when i == iMin as well, so it is unnecessary to check.)

    In the loop, when we update iMin or iMax, we have already examined array[iMin] or array[iMax], respectively. iMin refers to the index that has a smaller value than the one we are looking for, and iMax to the index that has a larger value than the one we are looking for. So, we are essentially considering only array elements at indexes larger than iMin but smaller than iMax; excluding indexes iMin and iMax.