/*

 * bin_srch.c

 * This program generates a sorted array of integers and lets the user query

 * for numbers. It uses binary search to answer the queries efficiently.

 */

 

#include <stdio.h>

#include <stdlib.h>

 

#define MAX_SIZE 100

 

/* Prototypes: */

int bin_search (const int *arr, int n, int q);

 

int main ()

{

  int       array[MAX_SIZE];

  const int max_step = 10;

  int       step;

  int       curr;

  int       i;

 

  /* Fill the array with randomal ascending numbers. */

  array[0] = 1;


  srand (time (NULL));

  for (i = 1; i < MAX_SIZE; i++)

  {

    /* Pick a step size between 1 and max_step. */

    step = 1 + (int)(max_step * (float)rand() / (RAND_MAX + 1.0));

 

    array[i] = array[i - 1] + step;

  }

 

  /* Print out the array. */

  for (i = 0; i < MAX_SIZE; i++)

    printf ("%d ", array[i]);

  printf ("\n");

 

  /* Answer the user's queries. */

  while (1)

  {

    /* Read the next number. */

    printf ("Please enter a number (or < 0 to stop): ");

    scanf ("%d", &curr);

 

    if (curr <= 0)

      break;

 

    /* Search for it and print the result. */

    i = bin_search (array, MAX_SIZE, curr);

 

    if (i < 0)

      printf (" (%d) is not found in the array.\n", curr);

    else

      printf (" (%d) is found in index %d of the array.\n", curr, i);

  }

 

  return (0);

}

 

/* ------------------------------------------------------------------------

 * Function: bin_search

 * Purpose : Perform binary search to locate a query in a sorted array of

 *           integers.

 * Input   : arr - A sorted array of integers.

 *           n   - Its size.

 *           q   - The number being queried.

 * Returns : The index of the queried number in the array,

 *           or (-1) if it is not found.

 */

int bin_search (const int *arr, int n, int q)

{

  int     i_low;

  int     i_high;

  int     i_mid;

 

  /* The initial search range is the entire array. */

  i_low = 0;

  i_high = n - 1;

 

  while (i_high - i_low > 1)

  {

    printf (".");

 

    /* Find the index of the element at the middle of the current range:

    

           ---------- ( -------------- + -------------- ) ----

                     i_low           i_mid            i_high

     */

    i_mid = (i_low + i_high) / 2;

 

    /* Compare it to q and act accordingly. */

    if (arr[i_mid] == q)

    {

      /* Found the query: */

      return (i_mid);

    }

    else if (arr[i_mid] > q)

    {

      /* Continue with the range to the left of i_mid: */

      i_high = i_mid - 1;

    }

    else

    {

      /* Continue with the range to the right of i_mid: */

      i_low = i_mid + 1;

    }

  }

 

  /* At this point, the range contains 2 elements (at most), compare them to

     q before giving up. */

  if (arr[i_low] == q)

    return (i_low);

  else if (arr[i_high] == q)

    return (i_high);

 

  /* If we reached here, q is not found in the array. */

  return (-1);

}