I wrote a generic binary search routine in C++ for ranges that are specified by random access iterators. In case the user inputs a range with non-random access iterators, an exception will be thrown. My code is below:
binary_search.h
#ifndef CODERODDE_BINARY_SEARCH_H
#define CODERODDE_BINARY_SEARCH_H
#include <iterator>
namespace coderodde {
template<typename RandomIt, typename T>
RandomIt search(RandomIt begin,
RandomIt end,
T value,
std::random_access_iterator_tag)
{
RandomIt save_end = end;
while (begin != end)
{
RandomIt middle = begin + ((end - begin) >> 1);
if (value < *middle)
{
end = middle;
}
else if (value > *middle)
{
begin = middle + 1;
}
else
{
return middle;
}
}
return save_end;
}
template<typename NonRandomIt, typename T>
NonRandomIt search(NonRandomIt begin,
NonRandomIt end,
T value,
std::input_iterator_tag)
{
throw std::runtime_error(
"coderodde::search requires random access iterators.");
}
template<typename It, typename T>
It search(It begin, It end, T value)
{
return search(begin, end, value, typename std::iterator_traits<It>::iterator_category());
}
}
#endif /* CODERODDE_BINARY_SEARCH_H */
And the demonstration code is:
#include <iostream>
#include <iterator>
#include <list>
#include <stdexcept>
#include <vector>
#include "binary_search.h"
using coderodde::search;
using std::boolalpha;
using std::cerr;
using std::cout;
using std::end;
using std::endl;
using std::list;
using std::runtime_error;
using std::vector;
int main() {
cout << "int array:" << endl;
int arr[] = { 1, 3, 4, 4, 5, 7, 10, 15, 23 };
size_t length = sizeof(arr) / sizeof(arr[0]);
int* p = search(arr, arr + length, 1);
cout << "The 1st iterator points to: " << *p << endl;
p = search(arr, arr + length, 7);
cout << "The 2nd iterator points to: " << *p << endl;
p = search(arr, arr + length, 23);
cout << "The 3rd iterator points to: " << *p << endl;
p = search(arr, arr + length, 8);
cout << "8 not found: " << boolalpha << (p == end(arr)) << endl;
cout << "int vector:" << endl;
vector<int> vec = { 1, 3, 4, 4, 5, 7, 10, 15, 23 };
vector<int>::iterator it = search(vec.begin(), vec.end(), 1);
cout << "The 1st iterator points to: " << *it << endl;
it = search(vec.begin(), vec.end(), 7);
cout << "The 2nd iterator points to: " << *it << endl;
it = search(vec.begin(), vec.end(), 23);
cout << "The 3rd iterator points to: " << *it << endl;
p = search(arr, arr + length, 8);
cout << "8 not found: " << boolalpha << (p == end(arr)) << endl;
try {
list<int> lst = { 1, 3, 4, 4, 5, 7, 10, 15, 23 };
search(lst.begin(), lst.end(), 4);
} catch (runtime_error& err) {
cerr << err.what() << endl;
}
}
The output is:
int array: The 1st iterator points to: 1 The 2nd iterator points to: 7 The 3rd iterator points to: 23 8 not found: true int vector: The 1st iterator points to: 1 The 2nd iterator points to: 7 The 3rd iterator points to: 23 8 not found: true coderodde::search requires random access iterators.
As always, any critique is much appreciated.