Пространства имён
Варианты
Действия

std::upper_bound

Материал из cppreference.com
< cpp‎ | algorithm
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы над диапазонами (C++20)
Ограниченные алгоритмы, например ranges::copy, ranges::sort, ...
Политики исполнения (C++17)
Немодифицирующие операции над последовательностями
(C++11)(C++11)(C++11)
(C++17)
Модифицирующие операции над последовательностями
Операции разбиения
Операции сортировки
(C++11)
Операции двоичного поиска
upper_bound
Операции с наборами (в отсортированных диапазонах)
Операции с кучей
(C++11)
Операций минимума/максимума
(C++11)
(C++17)

Операции перестановки
Числовые операции
Операции с неинициализированной памятью
(C++17)
(C++17)
(C++17)
Библиотека C
 

Содержание

[править] Объявление

Определено в заголовочном файле <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)

[править] Описание

Возвращает минимальную (первую) позицию элемента входящего в диапазон [firstlast) и имеющего значение больше чем value. Возвращает last, если такого элемента нет в диапазоне. См. Диапазоны См. #Постусловия. Если диапазон не частично упорядочен относительно value, то поведение не определено. См. #Предусловия.

1) для сравнения значений элементов использует operator<. Вариант эквивалентен std::upper_bound(first, last, value, std::less{}) (начиная с C++20).
2) для сравнения значений элементов использует функцию(предикат) comp.

[править] Параметры

[firstlast) два итератора задающих диапазон элементов (частично упорядоченных)
value Значение для сравнения с элементами в диапазоне
comp объект функции сравнения (т.е. объект, удовлетворяющий требованиям Compare), который возвращает true, если первый аргумент "меньше", чем второй.

Определение сравнения должно быть эквивалентно:

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

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

Требования к типам
-
ForwardIt должен соответствовать требованиям ForwardIterator.
-
Compare должен соответствовать требованиям BinaryPredicate. It is not required to satisfy Compare.

[править] Возвращаемое значение

итератор диапазона [firstlast), указывающий на первый элемент со значением больше чем value, или last (если такой элемент не найден).

[править] Предусловия

[[assume(
  (std::forward_iterator<ForwardIt>)&& //См. [[#Параметры]]
  (std::binary_predicate<Compare>)&&
  (!comp(value,value))&&
  (std::is_partitioned(first,last,std::bind(comp,value)))
)]];

Предусловия comp, std::bind и std::is_partitioned тоже должны выполняться. Возможное предусловие [[assume(std::is_sorted(first,last,comp))]] достаточно, но избыточно.

[править] Постусловия

auto result=std::upper_bound(first,last,comp);
[[assume((result==last)||(comp(value,*result)))]]
[[assume((result==first)||(!comp(value,*std::prev(result))))]]
[[assume(!(std::distance(first ,result)<0))]]
[[assume(!(std::distance(result,  last)<0))]]
Предусловия std::upper_bound тоже выполняются.

[править] Исключения

Обеспечивает наивысшую гарантию обработки исключений, но не выше чем Compare и чем ForwardIt.

[править] Сложность

Память=O(1)+O(Compare)+O(ForwardIt)
Время=log
2
(std::distance(first, last))+O(1)
сравнений элементов.
Однако если ForwardIt не LegacyRandomAccessIterator, то время линейно зависит от std::distance(first, last). Например, итераторы в std::map, std::multimap, std::set, и std::multiset не являются LegacyRandomAccessIterator, поэтому вместо std::upper_bound используйте аналогичные функции соответствующих контейнеров.

[править] Заметки

Хотя std::upper_bound требует на диапазоне [firstlast) только лишь частичного разбиения предикатом std::bind(comp,value), этот алгоритм обычно используется в случаях, когда [firstlast) полностью отсортирован, поэтому бинарный поиск допустим для любого значения.

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

[править] Возможная реализация

См. libstdc++ и libc++.

Первый вариант
template<
  class ForwardIt
  ,class T       //= typename std::iterator_traits<ForwardIt>::value_type
  ,class Compare //= typename std::less<T>
>//constexpr
ForwardIt upper_bound (
  ForwardIt first, ForwardIt last
  ,T const& value
  ,Compare comp = std::less<T>()
)
{
  typedef typename std::iterator_traits<ForwardIt>::distance_type dist; //use auto
  for(dist count = std::distance (first,last); !(count==0); ) {
    dist step( count / 2 );
    ForwardIt it( first );
    std::advance (it, step);
    if ( comp (value,*it) ) count = step;
    else {
      first = ++it; //first = std::next(it);
      count = count - step - 1;
    }
    return first;
}
Второй вариант
template<class ForwardIt, class T, class Compare>
ForwardIt upper_bound(ForwardIt first, ForwardIt last,
                            const T& value, Compare comp)
{
    ForwardIt it;
    std::iterator_traits<ForwardIt>::distance_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;
}

[править] Пример

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
 
int main()
{
    std::vector<int> data = { 1, 1, 2, 3, 3, 3, 3, 4, 4, 4, 5, 5, 6 };
 
    auto lower = std::lower_bound(data.begin(), data.end(), 4);
    auto upper = std::upper_bound(data.begin(), data.end(), 4);
 
    std::copy(lower, upper, std::ostream_iterator<int>(std::cout, " "));
}

Вывод:

4 4 4

[править] Defect reports

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

Номер Применён Поведение в стандарте Корректное поведение
LWG 270 C++98 Compare was required to satisfy Compare and T was required
to be LessThanComparable (strict weak ordering required)
only a partitioning is required;
heterogeneous comparisons permitted
LWG 384 C++98 at most log
2
(N)+1
comparisons were allowed
corrected to log
2
(N)+O(1)
LWG 577 C++98 last could not be returned allowed
LWG 2150 C++98 if any iterator iter exists in [firstlast) such that
bool(comp(value, *iter)) is true, std::lower_bound
could return any iterator in [iterlast)
no iterator after
iter can be returned

[править] См. также

возвращает итератор на первый элемент, который больше определённого значения
(ниблоид) [править]
возвращает итератор на первый элемент больший, чем заданный ключ
(public функция-элемент std::set) [править]
возвращает итератор на первый элемент больший, чем заданный ключ
(public функция-элемент std::multiset) [править]
возвращает итератор на первый элемент больший, чем заданный ключ
(public функция-элемент std::map) [править]
возвращает итератор на первый элемент больший, чем заданный ключ
(public функция-элемент std::multimap) [править]
возвращает итератор на первый элемент не меньший, чем заданное значение
(шаблон функции) [править]
определяет, существует ли элемент в частично упорядоченном диапазоне
(шаблон функции) [править]
ищет диапазон элементов
(шаблон функции) [править]
возвращает диапазон элементов, соответствующих определённому ключу
(шаблон функции) [править]
сортирует диапазон в порядке возрастания
(шаблон функции) [править]
(C++11)
проверяет, отсортирован ли диапазон по возрастанию
(шаблон функции) [править]
дели�� диапазон элементов на две группы
(шаблон функции) [править]
определяет, разделён ли диапазон заданным предикатом
(шаблон функции) [править]
находит точку раздела разделённого на две группы диапазона
(шаблон функции) [править]