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, если первый аргумент меньше (т.е. упорядочен перед) второго. Подпись функции-предиката должна быть эквивалентна следующей:
Хотя подпись не обязательно должна содержать |
| Требования к типу | ||
-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) |
См. также
| возвращает диапазон элементов, соответствующих заданному ключу (шаблон функции) |
|
| делит диапазон элементов на две группы (шаблон функции) |
|
|
(C++11) | находит точку разбиения разбённого диапазона (шаблон функции) |
| возвращает итератор на первый элемент, больше определённого значения (шаблон функции) |
|
| возвращает итератор на первый элемент, не меньше заданного ключа (публичный метод std::set<Key,Compare,Allocator>) |
|
| возвращает итератор на первый элемент, не меньше заданного ключа (публичный метод std::multiset<Key,Compare,Allocator>) |
|
|
(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