Spec-Zone.ru › C++

std::lower_bound

Определено в заголовке <algorithm>
(1)
template< class ForwardIt, class T >
ForwardIt lower_bound( ForwardIt first, ForwardIt last, const T& value );
(до C++20)
template< class ForwardIt, class T >
constexpr ForwardIt lower_bound( ForwardIt first, ForwardIt last,
                                 const T& value );
(с C++20)
(2)
template< class ForwardIt, class T, class Compare >
ForwardIt lower_bound( ForwardIt first, ForwardIt last,
                       const T& value, Compare comp );
(до C++20)
template< class ForwardIt, class T, class Compare >
constexpr ForwardIt lower_bound( ForwardIt first, ForwardIt last,
                                 const T& value, Compare comp );
(с C++20)

Возвращает итератор, указывающий на первый элемент в диапазоне [first, last) такой, что element < value (или comp(element, value)) является false, (т.е. не меньше value) или last, если такой элемент не найден.

Диапазон [first, last) должен быть разбит относительно выражения element < value (или comp(element, value)) , то есть все элементы, для которых выражение является true, должны предшествовать всем элементам, для которых выражение является false. Полностью отсортированный диапазон удовлетворяет этому критерию.

Первый вариант использует оператор< для сравнения элементов, второй вариант использует заданную функцию сравнения comp.

Параметры

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

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

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

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

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

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

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

Сложность

Число выполненных сравнений логарифмически зависит от расстояния между first и last (не более log2(last - first) + O(1) сравнений). Однако для не-LegacyRandomAccessIterators количество приращений итератора линейно. Обратите внимание, что std::map, std::multimap, std::set, и std::multiset итераторы не являются произвольным доступом, поэтому следует предпочесть их функции-члены lower_bound.

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

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

lower_bound (1)
template<class ForwardIt, class T>
ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value)
{
    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 (*it < value)
        {
            first = ++it; 
            count -= step + 1; 
        }
        else
            count = step;
    }
 
    return first;
}
lower_bound (2)
template<class ForwardIt, class T, class Compare>
ForwardIt lower_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(*it, value))
        {
            first = ++it;
            count -= step + 1;
        }
        else
            count = step;
    }
 
    return first;
}

Пример

#include <algorithm>
#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 < 8; ++i)
    {
        // Search for first element x such that i ≤ x
        auto lower = std::lower_bound(data.begin(), data.end(), i);
 
        std::cout << i << " ≤ ";
        lower != data.end()
            ? std::cout << *lower << " at index " << std::distance(data.begin(), lower)
            : std::cout << "not found";
        std::cout << '\n';
    }
 
    std::vector<PriceInfo> prices{{100.0}, {101.5}, {102.5}, {102.5}, {107.3}};
 
    for (const double to_find : {102.5, 110.2})
    {
        auto prc_info = std::lower_bound(prices.begin(), prices.end(), to_find,
            [](const PriceInfo& info, double value)
            {
                return info.price < value;
            });
 
        prc_info != prices.end()
            ? std::cout << prc_info->price << " at index " << prc_info - prices.begin()
            : std::cout << to_find << " not found";
        std::cout << '\n';
    }
}

Вывод:

0 ≤ 1 at index 0
1 ≤ 1 at index 0
2 ≤ 2 at index 1
3 ≤ 4 at index 2
4 ≤ 4 at index 2
5 ≤ 5 at index 3
6 ≤ 6 at index 5
7 ≤ not found
102.5 at index 2
110.2 not found

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

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

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

См. также

equal_range
возвращает диапазон элементов, соответствующих заданному ключу
(шаблон функции)
partition
делит диапазон элементов на две группы
(шаблон функции)
partition_point
(C++11)
находит точку разбиения разбённого диапазона
(шаблон функции)
upper_bound
возвращает итератор на первый элемент, больше определённого значения
(шаблон функции)
lower_bound
возвращает итератор на первый элемент, не меньше заданного ключа
(публичный метод std::set<Key,Compare,Allocator>)
lower_bound
возвращает итератор на первый элемент, не меньше заданного ключа
(публичный метод std::multiset<Key,Compare,Allocator>)
ranges::lower_bound
(C++20)
возвращает итератор на первый элемент, не меньше заданного значения
(niebloid)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/algorithm/lower_bound

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API