В моем поиске быстрого поиска элемента в векторе с использованием двоичного поиска я нашел функцию std :: binary_search, но потом понял, что возвращает только bool, к моему ужасу.
Но тогда я нашел наиболее распространенное решение для поиска элемента таким образом, чтобы связать binary_search() с lower_bound(). Посмотрев на него ближе, я думаю, что lower_bound() также ищет элемент, используя ситуацию с бинарным поиском. Значит, это не значит, что я ищу его дважды?
Это пример того, что я имею в виду: std :: vector haystack {1, 3, 4, 5, 9}; int needle = 5;
if (std::binary_search(haystack.begin(), haystack.end(), needle)) {
std::cout << "Found " << needle << '\n';
std::vector<int>::iterator it = lower_bound(haystack.begin(), haystack.end(), needle);
int result = *it;
cout << "Result " << result << endl;
}
Я просто делаю это неправильно? Есть ли другой способ бинарного поиска чего-то внутри вектора и получить фактический найденный элемент?
Да, вы делаете два бинарных поиска. Просто используйте lower_bound
один раз с дополнительным сравнением:
auto it = std::lower_bound(haystack.begin(), haystack.end(), needle);
if (it != haystack.end() && *it == needle) {
// found it, here.
}
Но делайте это только в том случае, если вам нужен итератор. Если вы просто хотите проверить наличие needle
, я бы использовал std::binary_search()
для большей ясности для ваших пользователей. Который вполне может быть реализован с точки зрения lower_bound
для начала. Из cppreference:
template<class ForwardIt, class T>
bool binary_search(ForwardIt first, ForwardIt last, const T& value)
{
first = std::lower_bound(first, last, value);
return (!(first == last) && !(value < *first));
}
Да, это делает дублирующую работу. Вы можете использовать std::lower_bound
даже если вы не уверены, находится ли элемент в коллекции или нет; если это не так, он вернет конечный итератор. Поэтому вы можете использовать следующее:
auto it = lower_bound(haystack.begin(), haystack.end(), needle);
if (it != haystack.end() && *it == needle) {
cout << "Found " << needle << '\n';
cout << "Result " << *it << '\n';
}
Предположим, что needle
находится в стоге сена. Тогда, конечно, needle
станет первым элементом, который не меньше, чем needle
, и поэтому вы его найдете.
Если needle
не находится в стоге сена, и все элементы меньше, чем needle
, то возвращается конечный итератор, и проверка it != haystack.end()
завершится неудачно.
Если есть элемент, меньший, чем needle
то итератор it
ему будет возвращен, но проверка *it == needle
провалится.
В любом случае, вы получите желаемый результат.