Namespaces
Variants

std:: upper_bound

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
upper_bound
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Определено в заголовке <algorithm>
(1)
template < class ForwardIt, class T >

ForwardIt upper_bound ( ForwardIt first, ForwardIt last,

const T & value ) ;
(constexpr начиная с C++20)
(до C++26)
template < class ForwardIt, class T = typename std:: iterator_traits

< ForwardIt > :: value_type >
constexpr ForwardIt upper_bound ( ForwardIt first, ForwardIt last,

const T & value ) ;
(начиная с C++26)
(2)
template < class ForwardIt, class T, class Compare >

ForwardIt upper_bound ( ForwardIt first, ForwardIt last,

const T & value, Compare comp ) ;
(constexpr начиная с C++20)
(до C++26)
template < class ForwardIt, class T = typename std:: iterator_traits

< ForwardIt > :: value_type ,
class Compare >
constexpr ForwardIt upper_bound ( ForwardIt first, ForwardIt last,

const T & value, Compare comp ) ;
(начиная с C++26)

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

1) Порядок определяется с помощью operator < :

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

Если элементы elem в диапазоне [ first , last ) не являются отсортированными относительно выражения bool ( value < elem ) , поведение не определено.

(до C++20)

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

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

Содержание

Параметры

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

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

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

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

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

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

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

Сложность

Дано N как std:: distance ( first, last ) :

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

Однако, если ForwardIt не является LegacyRandomAccessIterator , количество инкрементов итератора линейно зависит от N . В частности, итераторы std::map , std::multimap , std::set и std::multiset не являются итераторами произвольного доступа, поэтому следует предпочитать их функции-члены upper_bound .

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

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

upper_bound (1)
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type>
ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value)
{
    return std::upper_bound(first, last, value, std::less{});
}
upper_bound (2)
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type,
         class Compare>
ForwardIt upper_bound(ForwardIt first, ForwardIt last, const T& value, Compare comp)
{
    ForwardIt it;
    typename std::iterator_traits<ForwardIt>::difference_type count, step;
    count = std::distance(first, last);
    while (count > 0)
    {
        it = first; 
        step = count / 2;
        std::advance(it, step);
        if (!comp(value, *it))
        {
            first = ++it;
            count -= step + 1;
        } 
        else
            count = step;
    }
    return first;
}
**Примечание:** Весь код C++ внутри тегов `
` и `` оставлен без изменений, как и требовалось. HTML-теги и атрибуты также сохранены в оригинальном виде. Переведены только текстовые элементы на странице.

Примечания

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

Для любого итератора iter в диапазоне [ first , last ) , std::upper_bound требует, чтобы выражения value < * iter и comp ( value, * iter ) были корректно сформированы, тогда как std::lower_bound требует, чтобы выражения * iter < value и comp ( * iter, value ) были корректно сформированы вместо этого.

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

Пример

#include <algorithm>
#include <cassert>
#include <complex>
#include <iostream>
#include <vector>
struct PriceInfo { double price; };
int main()
{
    const std::vector<int> data{1, 2, 4, 5, 5, 6};
    for (int i = 0; i < 7; ++i)
    {
        // Поиск первого элемента, большего чем i
        auto upper = std::upper_bound(data.begin(), data.end(), i);
        std::cout << i << " < ";
        upper != data.end()
            ? std::cout << *upper << " по индексу " << std::distance(data.begin(), upper)
            : std::cout << "не найдено";
        std::cout << '\n';
    }
    std::vector<PriceInfo> prices{{100.0}, {101.5}, {102.5}, {102.5}, {107.3}};
    for (double to_find : {102.5, 110.2})
    {
        auto prc_info = std::upper_bound(prices.begin(), prices.end(), to_find,
            [](double value, const PriceInfo& info)
            {
                return value < info.price;
            });
        prc_info != prices.end()
            ? std::cout << prc_info->price << " по индексу " << prc_info - prices.begin()
            : std::cout << to_find << " не найдено";
        std::cout << '\n';
    }
    using CD = std::complex<double>;
    std::vector<CD> nums{{1, 0}, {2, 2}, {2, 1}, {3, 0}, {3, 1}};
    auto cmpz = [](CD x, CD y) { return x.real() < y.real(); };
    #ifdef __cpp_lib_algorithm_default_value_type
        auto it = std::upper_bound(nums.cbegin(), nums.cend(), {2, 0}, cmpz);
    #else
        auto it = std::upper_bound(nums.cbegin(), nums.cend(), CD{2, 0}, cmpz);
    #endif
    assert((*it == CD{3, 0}));
}

Вывод:

0 < 1 по индексу 0
1 < 2 по индексу 1
2 < 4 по индексу 2
3 < 4 по индексу 2
4 < 5 по индексу 3
5 < 6 по индексу 5
6 < не найдено 
107.3 по индексу 4
110.2 не найдено

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

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

DR Применяется к Поведение в опубликованной версии Корректное поведение
LWG 270 C++98 Compare требовалось удовлетворять Compare и T требовался
быть LessThanComparable (требовался строгий слабый порядок)
требуется только разделение;
разрешены гетерогенные сравнения
LWG 384 C++98 допускалось не более log 2 (N)+1 сравнений исправлено на log 2 (N)+O(1)
LWG 577 C++98 last не мог быть возвращён разрешено
LWG 2150 C++98 если существует любой итератор iter в [ first , last ) такой, что
bool ( comp ( value, * iter ) ) равен true , std::upper_bound
мог возвращать любой итератор в [ iter , last )
никакой итератор после
iter не может быть возвращён

Смотрите также

возвращает диапазон элементов, соответствующих заданному ключу
(шаблон функции)
возвращает итератор на первый элемент не меньший заданного значения
(шаблон функции)
разделяет диапазон элементов на две группы
(шаблон функции)
находит точку разделения разделённого диапазона
(шаблон функции)
возвращает итератор на первый элемент больший определённого значения
(функциональный объект алгоритма)
возвращает итератор на первый элемент больший заданного ключа
(публичная функция-член std::set<Key,Compare,Allocator> )
возвращает итератор на первый элемент больший заданного ключа
(публичная функция-член std::multiset<Key,Compare,Allocator> )