C, search, exponential_search.c

/**
 *  \file
 *  \brief [Exponential Search](https://github.com/TheAlgorithms/Algorithms-Explanation/blob/master/en/Search%20Algorithms/Exponential%20Search.md)
 *  \author [Alessio Farinelli](https://github.com/faridevnz)
 */
#include <assert.h>  /// for assert
#include <inttypes.h>  /// for int64_t, uint16_t

#define ELEMENT -10

int64_t binary_search(const int64_t* arr, const uint16_t l_index, const uint16_t r_index, const int64_t n); ///< used to perform the binary search over the given array
int64_t exponential_search(const int64_t* arr, const uint16_t length, const int64_t n); ///< used to perform the exponential search over the given array
static void test(); ///< used to run the self-test implementations

/**
 * Function: exponential_search
 * \brief algorithm that search the index of the given item
 * \details recursive function that take an array and quickly find the range 
 * where to apply the binary search algorithm to find the given element
 * ----------------------------
 * \param arr array where search the element
 * \param length the total length of the given array (arr)
 * \param n element to find in the array (arr)
 * 
 * \returns the index of the element (n) in the array (arr)
 * \returns -1 if the element wasn't found
 */
int64_t exponential_search(const int64_t* arr, const uint16_t length, const int64_t n) 
{
    if ( length == 0 ) { return -1; }
    // find the upperbound
    uint32_t upper_bound = 1;
    while ( upper_bound <= length && arr[upper_bound] < n ) { upper_bound = upper_bound * 2; }
    // calculate the range ( between lower_boud and upper_bound )
    uint16_t lower_bound = upper_bound/2;
    if ( upper_bound > length ) { upper_bound = length; }
    // apply the binary search in the range
    return binary_search(arr, lower_bound, upper_bound, n);
}

/**
 * Function: binary_search
 * \brief algorithm that search the index of the given item
 * \details recursive function that search the given element in
 * the array using the [Binary Search](https://github.com/TheAlgorithms/Algorithms-Explanation/blob/master/en/Search%20Algorithms/Binary%20Search.md)
 * ----------------------------
 * \param arr array where search the element
 * \param l_index start index of the array (arr) to apply the algorithm
 * \param r_index end index of the array (arr) to apply the algorithm
 * \param n element to find in the array (arr)
 *
 * \returns the index of the element (n) in the array (arr)
 * \returns -1 if the n element wasn't found
 */
int64_t binary_search(const int64_t* arr, const uint16_t l_index, const uint16_t r_index, const int64_t n) 
{
    // calculate the middle index of the array
    uint16_t middle_index = l_index + ( r_index - l_index ) / 2;
    // base cases
    if ( l_index > r_index ) { return -1; }
    if ( arr[middle_index] == n ) { return middle_index; }
    // recursion
    if ( arr[middle_index] > n ) { return binary_search(arr, l_index, middle_index-1, n); } // left
    return binary_search(arr, middle_index+1, r_index, n); // right
}

/**
 * @brief Main function
 * @returns 0 on exit
 */
int main() 
{
    test();  // run self-test implementations
    return 0;
}

/**
 * @brief Self-test implementations
 * @returns void
 */
static void test()
{
    // empty array
    int64_t arr_empty[] = {};
    assert(exponential_search(arr_empty, 0, 10) == -1);
    // elent not found
    int64_t arr_found[] = {1, 2, 3};
    assert(exponential_search(arr_found, 3, 10) == -1);
    // element found in an array of length 1
    int64_t arr_one[] = {1};
    assert(exponential_search(arr_found, 1, 1) == 0);
    // find the first element in an array of length 2
    int64_t arr_first_2[] = {1, 2};
    assert(exponential_search(arr_first_2, 2, 1) == 0);
    // find the last element in an array of length 2
    int64_t arr_last_2[] = {1, 2};
    assert(exponential_search(arr_last_2, 2, 2) == 1);
    // find the first element in an array of length n
    int64_t arr_first_n[] = {-1, 2, 4, 6, 8};
    assert(exponential_search(arr_first_n, 5, -1) == 0);
    // find the last element in an array of length n
    int64_t arr_last_n[] = {-1, 2, 4, 6, 8};
    assert(exponential_search(arr_last_n, 5, 8) == 4);
    // find an element in an array of length n
    int64_t arr_middle[] = {-1, 2, 4, 6, 8};
    assert(exponential_search(arr_middle, 5, 6) == 3);
}