namespace std::ranges {
template <forward_iterator I,
sentinel_for<I> S,
class T,
class Proj = identity,
indirect_strict_weak_order<const T*, projected<I, Proj>> Comp = ranges::less>
constexpr I
lower_bound(I first,
S last,
const T& value,
Comp comp = {},
Proj proj = {}); // (1) C++20
template <forward_range R,
class T,
class Proj = identity,
indirect_strict_weak_order<const T*, projected<iterator_t<R>, Proj>> Comp = ranges::less>
constexpr borrowed_iterator_t<R>
lower_bound(R&& r,
const T& value,
Comp comp = {},
Proj proj = {}); // (2) C++20
}
概要
指定された要素以上の値が現れる最初の位置のイテレータを取得する。
- (1): イテレータ範囲を指定する
- (2): Rangeを直接指定する
この関数の用途としては、ソート済み範囲に対して、任意の値を二分探索で見つけるために使用できる。std::multiset
のように同じキーを持つ要素が複数あり、その全てを列挙したい場合にはこの関数の代わりにstd::ranges::equal_range()
関数を使用できる。
事前条件
[first,last)
の要素e
はe < value
またはcomp(e, value)
によって区分化されていること。 つまり、e < value
またはcomp(e, value)
がtrue
となる全ての要素e
は、false
となる全ての要素よりも左側(first
に近い方)になければならない。
戻り値
[first, last]
内のイテレータ i
のうち、以下の条件を満たす、最も右側(first
から遠い方)のもの
[first, i)
内の全てのイテレータj
が*j < value
またはcomp(*j, value) != false
である
(つまり、value
以上の要素のうち最初のものを指すイテレータ。value
以上の要素が無ければ last
)
計算量
最大で log2(last - first
) + O(1) 回の比較を行う
例
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
struct X {
int id;
std::string name;
};
int main()
{
// この関数単体としての使い方
{
// lower_bound で 4 以上の要素の位置を検索する場合、
// 4 より小さい物と 4 以上の物がその順に並んでいれば、
// 必ずしもソートされている必要はない。
std::vector<int> v = {3, 1, 4, 6, 5};
// 4以上の要素を二分探索で検索
auto it = std::ranges::lower_bound(v, 4);
if (it != v.end()) {
std::size_t pos = std::ranges::distance(v.begin(), it);
std::cout << *it << " pos=" << pos << std::endl;
}
}
// 基本的な用途
// ソート済み範囲から、特定の値を二分探索で見つける
{
std::vector<int> v = {3, 1, 4, 6, 5};
std::ranges::sort(v);
// 二分探索で値4を検索
auto it = std::ranges::lower_bound(v, 4);
if (it != v.end() && *it == 4) { // lower_boundでは4"以上"の値が見つかるので、
// 値4を見つけたいなら検索結果の値を比較する必要がある
std::size_t pos = std::ranges::distance(v.begin(), it);
std::cout << *it << " pos=" << pos << std::endl;
}
}
// 要素の一部の値を比較して見つける
{
// 要素は複数のメンバ変数をもつ
std::vector<X> v = {
{1, "Carol"},
{3, "Alice"},
{4, "Bob"},
{5, "Eve"},
{6, "Dave"}
};
const std::string key = "Bob";
// X::nameメンバ変数をキーにして、
// X::name == "Bob"となる要素を二分探索で見つける
auto it = std::ranges::lower_bound(v, key, {}, &X::name);
if (it != v.end() && it->name == key) {
std::size_t pos = std::ranges::distance(v.begin(), it);
std::cout << "id=" << it->id
<< " name=" << it->name
<< " pos=" << pos
<< std::endl;
}
}
}
出力
4 pos=2
4 pos=2
id=4 name=Bob pos=2
バージョン
言語
- C++20
処理系
- Clang: ??
- GCC: 10.1.0 ✅
- ICC: ??
- Visual C++: 2019 Update 10 ✅