Означает ли комбинация C ++ std :: binary_search (), а затем std :: lower_bound (), что я выполняю двоичный поиск дважды?

0

В моем поиске быстрого поиска элемента в векторе с использованием двоичного поиска я нашел функцию 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;
}

Я просто делаю это неправильно? Есть ли другой способ бинарного поиска чего-то внутри вектора и получить фактический найденный элемент?

Теги:
c++11
iterator
vector
binary-search

2 ответа

4
Лучший ответ

Да, вы делаете два бинарных поиска. Просто используйте 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));
}
1

Да, это делает дублирующую работу. Вы можете использовать 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 провалится.

В любом случае, вы получите желаемый результат.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню