Namespaces
Variants

std::binary_search

С ru.cppreference.net
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы над диапазонами (C++20)
Ограниченные алгоритмы, например ranges::copy, ranges::sort, ...
Немодифицирующие последовательные операции    
Пакетные операции
(C++17)
Операции поиска
Модифицирующие последовательные операции
Операции копирования
(C++11)
(C++11)
Операции обмена
Операции преобразования
Операции генерации
Операции удаления
Операции изменения порядка
(до C++17)(C++11)
(C++20)(C++20)
Операции выборки
(C++17)

Операции сортировки и связанные с ними
Операции разделения
(C++11)    

Операции сортировки
Операции двоичного поиска
(по разбитым диапазонам)
Операции над множествами (на отсортированных диапазонах)
Операции слияния (на отсортированных диапазонах)
Операции с кучей
Операции минимума/максимума
(C++11)
(C++17)
Операции лексикографического сравнения
Операции перестановок


Политики выполнения (C++17)
(только для демонстрации*)(C++26)

Числовые операции
(C++11)
(C++17)
(C++17)    

Специализированные <memory> алгоритмы

Специализированные <random> алгоритмы
Библиотека C









 
Определён в заголовке <algorithm>
template< class ForwardIt, class T >
bool binary_search( ForwardIt first, ForwardIt last,
                    const T& value );
(1) (до C++26)
(constexpr начиная с C++20)
template< class ForwardIt, class T = typename std::iterator_traits
                                         <ForwardIt>::value_type >
constexpr bool binary_search( ForwardIt first, ForwardIt last,
                              const T& value );
(начиная с C++26)
template< class ForwardIt, class T, class Compare >
bool binary_search( ForwardIt first, ForwardIt last,
                    const T& value, Compare comp );
(2) (до C++26)
(constexpr начиная с C++20)
template< class ForwardIt, class T = typename std::iterator_traits
                                         <ForwardIt>::value_type,
          class Compare >
constexpr bool binary_search( ForwardIt first, ForwardIt last,
                              const T& value, Compare comp );
(начиная с C++26)

Проверяет, присутствует ли элемент, эквивалентный value, в разбитом диапазоне [first, last).

1) Эквивалентность проверяется с помощью operator<:

Если !bool(*iter < value) && !bool(value < *iter) равно true для некоторого итератора iter в [first, last), возвращает true. В противном случае возвращает false.

Если выполняется любое из следующих условий, поведение не определено:

  • Для любого элемента elem из [first, last), bool(elem < value) не влечёт !bool(value < elem).
  • Элементы elem из [first, last) не разбиты относительно выражений bool(elem < value) и !bool(value < elem).
(до C++20)

Эквивалентно std::binary_search(first, last, value, std::less{}).

(начиная с C++20)
2) Эквивалентность проверяется с помощью comp:
Если !bool(comp(*iter, value)) && !bool(comp(value, *iter)) равно true для некоторого итератора iter в [first, last), возвращает true. В противном случае возвращает false.
Если выполняется любое из следующих условий, поведение не определено:
  • Для любого элемента elem из [first, last), bool(comp(elem, value)) не влечёт !bool(comp(value, elem)).
  • Элементы elem из [first, last) не разбиты относительно выражений bool(comp(elem, value)) и !bool(comp(value, elem)).

Параметры

first, last - пара итераторов, определяющая разбитый диапазон для проверки элементов
value - значение для сравнения с элементами
comp - бинарный предикат, который возвращает ​true, если первый аргумент упорядочен перед вторым.

Сигнатура функции предиката должна быть эквивалентна следующей:

bool pred(const Type1 &a, const Type2 &b);

Хотя сигнатура не обязательно должна содержать const &, функция не должна изменять переданные ей объекты и должна быть способна принимать все значения типа (возможно, const) Type1 и Type2 независимо от категории значения (таким образом, Type1 & не разрешён, как и Type1, если только для Type1 перемещение не эквивалентно копированию(начиная с C++11)).
Типы Type1 и Type2 должны быть такими, чтобы объект типа T мог быть неявно преобразован как в Type1, так и в Type2, и объект типа ForwardIt мог быть разыменован, а затем неявно преобразован как в Type1, так и в Type2. ​

Требования к типам
-
ForwardIt должен удовлетворять требованиям LegacyForwardIterator.
-
Compare должен удовлетворять требованиям BinaryPredicate. От него не требуется удовлетворять Compare.

Возвращаемое значение

true если найден элемент, эквивалентный value, иначе false.

Сложность

Пусть N равно std::distance(first, last):

1) Не более log2(N)+O(1) сравнений с value с использованием operator<(до C++20)std::less{}(начиная с C++20).
2) Не более log2(N)+O(1) применений компаратора comp.

Однако, если ForwardIt не является LegacyRandomAccessIterator, количество инкрементов итератора линейно по N.

Примечания

Хотя std::binary_search требует только разбиения [first, last), этот алгоритм обычно используется в случае, когда [first, last) отсортирован, чтобы двоичный поиск был корректен для любого value.

std::binary_search только проверяет, существует ли эквивалентный элемент. Чтобы получить итератор на этот элемент (если он существует), следует использовать std::lower_bound.

Макрос тестирования возможности Значение Std Возможность
__cpp_lib_algorithm_default_value_type 202403 (C++26) List-initialization для алгоритмов (1,2)

Возможная реализация

См. также реализации в libstdc++ и libc++.

binary_search (1)
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type>
bool binary_search(ForwardIt first, ForwardIt last, const T& value)
{
    return std::binary_search(first, last, value, std::less{});
}
binary_search (2)
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type,
         class Compare>
bool binary_search(ForwardIt first, ForwardIt last, const T& value, Compare comp)
{
    first = std::lower_bound(first, last, value, comp);
    return (!(first == last) and !(comp(value, *first)));
}

Пример

#include <algorithm>
#include <cassert>
#include <complex>
#include <iostream>
#include <vector>

int main()
{
    const auto haystack = {1, 3, 4, 5, 9};
    
    for (const auto needle : {1, 2, 3})
    {
        std::cout << "Searching for " << needle << '\n';
        if (std::binary_search(haystack.begin(), haystack.end(), needle))
            std::cout << "Found " << needle << '\n';
        else
            std::cout << "Not found!\n";
    }

    using CD = std::complex<double>;
    std::vector<CD> nums{{1, 1}, {2, 3}, {4, 2}, {4, 3}};
    auto cmpz = [](CD x, CD y){ return abs(x) < abs(y); };
    #ifdef __cpp_lib_algorithm_default_value_type
        assert(std::binary_search(nums.cbegin(), nums.cend(), {4, 2}, cmpz));
    #else
        assert(std::binary_search(nums.cbegin(), nums.cend(), CD{4, 2}, cmpz));
    #endif
}

Вывод:

Searching for 1
Found 1
Searching for 2
Not found!
Searching for 3
Found 3

Отчёты о дефектах

Следующие отчёты о дефектах, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применён к Поведение в опубликованном виде Корректное поведение
LWG 270 C++98 Compare требовалось удовлетворять Compare, и T требовалось
быть LessThanComparable (требовалось строгое слабое упорядочение)
требуется только разбиение;
допускаются гетерогенные сравнения
LWG 787 C++98 допускалось не более log2(N)+2 сравнений исправлено на log2(N)+O(1)

См. также

находит диапазон элементов, соответствующих заданному значению, используя двоичный поиск
(шаблон функции & функциональный объект алгоритма)
находит первый элемент не меньше заданного значения, используя двоичный поиск
(шаблон функции & функциональный объект алгоритма)
находит первый элемент больше заданного, используя двоичный поиск
(шаблон функции & функциональный объект алгоритма)
определяет, существует ли элемент в диапазоне, используя двоичный поиск
(функциональный объект алгоритма)