diff --git a/search/fibonacci_search.cpp b/search/fibonacci_search.cpp new file mode 100644 index 000000000..be181a47d --- /dev/null +++ b/search/fibonacci_search.cpp @@ -0,0 +1,127 @@ +/** + * @author sprintyaf + * @file fibonacci_search.cpp + * @brief [Fibonacci search + * algorithm](https://en.wikipedia.org/wiki/Fibonacci_search_technique) + */ + +#include +#include // for std::vector class +#include // for assert +#include // for random numbers +#include // for sorting + + + +/** + * @brief using fibonacci search algorithm finds an index of a given element in a sorted array + * + * @param arr sorted array + * @param value value that we're looking for + * @returns if the array contains the value, returns an index of the element. otherwise -1. + */ +int fibonacci_search(const std::vector &arr, int value){ + // initialize last and current members of Fibonacci sequence + int last = 0, current = 1; + int length = arr.size(); // array size + // next member of Fibonacci sequence which is "last" + "current" + int next = last + current; + + // "next" will store the smallest Fibonacci number greater or equal to "length" + while(next < length){ + last = current; + current = next; + next = last + current; + } + + // "offset" is the end of eliminated range from front + int offset = -1, index; + // while loop until there are elements left to consider. + // when "next" becomes 1, last is equal to 0, so search is done, + // because arr[offset] will already be eliminated + while(next > 1){ + // check if "last" is valid location + index = std::min(offset + last, length-1); + // if value is greater than the value at "index", eliminate the subarray from offset to index + if(arr[index] < value){ + next = current; + current = last; + last = next - current; + offset = index; + // if value is less than the value at "index", eliminate the subarray after index+1 + } else if(arr[index] > value){ + next = last; + current = current - last; + last = next - current; + // element is found + } else { + return index; + } + } + // comparing the last element + if(current && !arr.empty() && arr[offset+1] == value){ + return offset+1; + } + // value was not found, return -1 + return -1; +} + +/** + * @brief random tests for checking performance when an array doesn't contain an element +*/ +bool no_occurence_tests(){ + bool passed = true; + int rand_num, rand_value, index, num_tests = 1000; + std::vector arr; + while(num_tests--){ + arr.clear(); + for(int i = 0; i < 100; i++){ + rand_num = std::rand() % 1000; + arr.push_back(rand_num); + } + rand_value = std::rand() % 1000; + while(std::find(arr.begin(), arr.end(), rand_value) != arr.end()){ + std::remove(arr.begin(), arr.end(), rand_value); + } + sort(arr.begin(), arr.end()); + index = fibonacci_search(arr, rand_value); + passed = passed && (index == -1); + } + return passed; +} + +/** + * @brief random tests which cover cases when we have one, multiple or zero occurences of the value we're looking for +*/ +bool random_tests(){ + bool passed = true; + int rand_num, rand_value, index, real_value, num_tests = 10000; + std::vector arr; + while(num_tests--){ + arr.clear(); + for(int i = 0; i < 100; i++){ + rand_num = std::rand() % 1000; + arr.push_back(rand_num); + } + rand_value = std::rand() % 1000; + std::sort(arr.begin(), arr.end()); + index = fibonacci_search(arr, rand_value); + if(index != -1){ + real_value = arr[index]; + passed = passed && (real_value == rand_value); + } else { + passed = passed && (std::find(arr.begin(), arr.end(), rand_value) == arr.end()); + } + } + return passed; +} + +/** + * Main Function + * testing the algorithm + */ +int main() { + assert(no_occurence_tests()); + assert(random_tests()); + return 0; +}