std::lower_bound
| ヘッダ <algorithm>
|
||
template< class ForwardIt, class T >
ForwardIt lower_bound( ForwardIt first, ForwardIt last,
const T& value );
|
で定義 (1) | (C++26まで) (constexpr C++20から) |
template< class ForwardIt, class T = typename std::iterator_traits
<ForwardIt>::value_type >
constexpr ForwardIt lower_bound( ForwardIt first, ForwardIt last,
const T& value );
|
(C++26から) | |
template< class ForwardIt, class T, class Compare >
ForwardIt lower_bound( ForwardIt first, ForwardIt last,
const T& value, Compare comp );
|
(2) | (C++26まで) (constexpr C++20から) |
template< class ForwardIt, class T = typename std::iterator_traits
<ForwardIt>::value_type,
class Compare >
constexpr ForwardIt lower_bound( ForwardIt first, ForwardIt last,
const T& value, Compare comp );
|
(C++26から) | |
分割された範囲 [first, last) 内で、よりも前に順序づけられていない最初の要素を検索します。
value1)
operator<|
内で
|
(C++20まで) |
|
|
(C++20から) |
comp によって決定されます:iter が [first, last) である bool(comp(*iter, value)) 内の最初のイテレータ false を返します。そのような last が存在しない場合は iter を返します。パラメータ
| first, last | - | パーティション分割された要素を調べる 範囲 を定義するイテレータのペア |
| value | - | 要素と比較する値 |
| comp | - |
第1引数が第2引数の前に順序付けられる場合に
true
を返す二項述語
述語関数のシグネチャは以下と同等であるべきです: bool pred ( const Type1 & a, const Type2 & b ) ;
シグネチャが
const
&
を持つ必要はありませんが、関数は渡されたオブジェクトを変更してはならず、
値カテゴリ
に関係なく型(おそらくconstの)
|
| 型要件 | ||
-
ForwardIt
は
LegacyForwardIterator
の要件を満たさなければなりません。
|
||
-
Compare
は
BinaryPredicate
の要件を満たさなければなりません。
Compare
を満たす必要はありません。
|
||
戻り値
範囲の最初の要素へのイテレータ
[
first
,
last
)
において
value
より順序付けされていない最初の要素、またはそのような要素が見つからない場合は
last
を返す。
計算量
与えられた N を std:: distance ( first, last ) として:
しかし、
ForwardIt
が
LegacyRandomAccessIterator
でない場合、イテレータのインクリメント回数は
N
に対して線形となる。特に、
std::map
、
std::multimap
、
std::set
、および
std::multiset
のイテレータはランダムアクセスではないため、それらのメンバ関数
lower_bound
を使用することが推奨される。
実装例
実装例については libstdc++ および libc++ も参照してください。
| lower_bound (1) |
|---|
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type> ForwardIt lower_bound(ForwardIt first, ForwardIt last, const T& value) { return std::lower_bound(first, last, value, std::less{}); } |
| lower_bound (2) |
template<class ForwardIt, class T = typename std::iterator_traits<ForwardIt>::value_type, 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; } |
注記
std::lower_boundは
[
first
,
last
)
が分割されていることのみを要求しますが、このアルゴリズムは通常、
[
first
,
last
)
がソートされている場合に使用され、これにより任意の
value
に対して二分探索が有効となります。
std::binary_search
とは異なり、
std::lower_bound
は
operator
<
または
comp
が非対称的(すなわち、
a
<
b
と
b
<
a
が常に異なる結果を返すこと)であることを要求しません。実際、
[
first
,
last
)
内の任意のイテレータ
iter
に対して
value
<
*
iter
または
comp
(
value,
*
iter
)
が適切に定義されていることすら要求しません。
| 機能テスト マクロ | 値 | 標準 | 機能 |
|---|---|---|---|
__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 < 8; ++i) { // 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'; } using CD = std::complex<double>; std::vector<CD> nums{{1, 0}, {2, 2}, {2, 1}, {3, 0}}; auto cmpz = [](CD x, CD y) { return x.real() < y.real(); }; #ifdef __cpp_lib_algorithm_default_value_type auto it = std::lower_bound(nums.cbegin(), nums.cend(), {2, 0}, cmpz); #else auto it = std::lower_bound(nums.cbegin(), nums.cend(), CD{2, 0}, cmpz); #endif assert((*it == CD{2, 2})); }
出力:
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(N)+1 回の比較が許可されていた | log 2 (N)+1 に修正 |
| LWG 2150 | C++98 |
[
first
,
last
)
内に
iter
が存在し、
bool ( comp ( * iter, value ) ) が false の場合、
std::lower_bound
は
[
iter
,
last
)
内の任意のイテレータを返す可能性があった
|
iter
以降のイテレータは
返されない |
関連項目
| 二分探索を使用して、指定された値に一致する要素の範囲を検出する (関数テンプレート & アルゴリズム関数オブジェクト) | |
(C++20) |
|
| 要素の範囲を2つのグループに分割する (関数テンプレート & アルゴリズム関数オブジェクト) | |
(C++20) |
|
(C++11) |
分割された範囲の分割点を特定する (関数テンプレート & アルゴリズム関数オブジェクト) |
(C++20) |
|
| 二分探索を使用して、指定された値よりも大きい最初の要素を検出する (関数テンプレート & アルゴリズム関数オブジェクト) | |
(C++20) |
|
| 指定されたキーよりも 小さくない最初の要素へのイテレータを返す ( std::set<Key,Compare,Allocator>のパブリックメンバ関数)
| |
| 指定されたキーよりも 小さくない最初の要素へのイテレータを返す ( std::multiset<Key,Compare,Allocator>のパブリックメンバ関数)
| |
(C++20) |
二分探索を使用して、指定された値よりも小さくない最初の要素を検出する (アルゴリズム関数オブジェクト) |