Namespaces
Variants

std::lower_bound

Von de.cppreference.net
 
 
Algorithmenbibliothek
Eingeschränkte Algorithmen und Algorithmen auf Bereichen (C++20)
Eingeschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Nicht modifizierende Sequenzoperationen    
Stapeloperationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Reihenfolgeändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
(C++11)    

Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Mischoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikografische Vergleichsoperationen
Permutationsoperationen


 
Definiert in Header <algorithm>
template< class ForwardIt, class T >
ForwardIt lower_bound( ForwardIt first, ForwardIt last,
                       const T& value );
(1) (bis C++26)
(constexpr seit 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 );
(seit C++26)
template< class ForwardIt, class T, class Compare >
ForwardIt lower_bound( ForwardIt first, ForwardIt last,
                       const T& value, Compare comp );
(2) (bis C++26)
(constexpr seit 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 );
(seit C++26)

Sucht nach dem ersten Element im partitionierten Bereich [first, last) das nicht vor value geordnet ist.

1) Die Reihenfolge wird durch operator< bestimmt:

Gibt den ersten Iterator iter in [first, last) zurück, für den bool(*iter < value) ist false, oder last wenn kein solcher iter existiert.

Wenn die Elemente elem von [first, last) nicht partitioniert in Bezug auf den Ausdruck bool(elem < value) sind, ist das Verhalten undefiniert.

(bis C++20)

Äquivalent zu std::lower_bound(first, last, value, std::less{}).

(seit C++20)
2) Die Reihenfolge wird durch comp bestimmt:
Gibt den ersten Iterator iter in [first, last) zurück, für den bool(comp(*iter, value)) ist false, oder last wenn kein solcher iter existiert.
Wenn die Elemente elem von [first, last) nicht partitioniert in Bezug auf den Ausdruck bool(comp(elem, value)) sind, ist das Verhalten undefiniert.

Parameter

first, last - das Paar von Iteratoren, das den partitionierten Bereich der zu untersuchenden Elemente definiert
value - Wert, mit dem die Elemente verglichen werden
comp - binäres Prädikat, das ​true zurückgibt, wenn das erste Argument vor dem zweiten geordnet ist.

Die Signatur der Prädikatfunktion sollte wie folgt sein:

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

Während die Signatur kein const & haben muss, darf die Funktion die übergebenen Objekte nicht modifizieren und muss alle Werte des Typs (möglicherweise const) Type1 und Type2 unabhängig von der Wertkategorie akzeptieren (daher ist Type1 & nicht erlaubt, ebenso wenig Type1 es sei denn, für Type1 ist eine Verschiebung gleichbedeutend mit einer Kopie(seit C++11)).
Der Typ Type1 muss so sein, dass ein Objekt vom Typ ForwardIt dereferenziert und dann implizit in Type1 konvertiert werden kann. Der Typ Type2 muss so sein, dass ein Objekt vom Typ T implizit in Type2 konvertiert werden kann. ​

Typanforderungen
-
ForwardIt muss die Anforderungen von LegacyForwardIterator erfüllen.
-
Compare muss die Anforderungen von BinaryPredicate erfüllen. Es ist nicht erforderlich, Compare zu erfüllen.

Rückgabewert

Iterator zum ersten Element des Bereichs [first, last), das nicht vor value geordnet ist, oder last, falls kein solches Element gefunden wird.

Komplexität

Gegeben N als std::distance(first, last):

1) Höchstens log2(N)+O(1) Vergleiche mit value unter Verwendung von operator<(bis C++20)std::less{}(seit C++20).
2) Höchstens log2(N)+O(1) Anwendungen des Komparators comp.

Falls ForwardIt kein LegacyRandomAccessIterator ist, ist die Anzahl der Iteratorinkremente linear in N. Insbesondere sind std::map, std::multimap, std::set und std::multiset Iteratoren kein wahlfreier Zugriff, daher sollten ihre lower_bound Member-Funktionen bevorzugt werden.

Mögliche Implementierung

Siehe auch die Implementierungen in libstdc++ und 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;
}

Anmerkungen

Obwohl std::lower_bound nur verlangt, dass [first, last) partitioniert ist, wird dieser Algorithmus normalerweise verwendet, wenn [first, last) sortiert ist, damit die binäre Suche für jedes value gültig ist.

Im Gegensatz zu std::binary_search erfordert std::lower_bound nicht, dass operator< oder comp asymmetrisch sind (d.h., a < b und b < a haben immer unterschiedliche Ergebnisse). Tatsächlich erfordert es nicht einmal, dass value < *iter oder comp(value, *iter) für einen Iterator iter in [first, last) wohlgeformt sind.

Feature-Test-Makro Wert Std Funktion
__cpp_lib_algorithm_default_value_type 202403 (C++26) Listeninitialisierung für Algorithmen (1,2)

Beispiel

#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)
    {
        // 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';
    }

    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}));
}

Ausgabe:

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

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Korrektes Verhalten
LWG 270 C++98 Compare musste Compare erfüllen und T musste
LessThanComparable sein (strenge schwache Ordnung erforderlich)
nur eine Partitionierung ist erforderlich;
heterogene Vergleiche erlaubt
LWG 384 C++98 höchstens log(N)+1 Vergleiche waren erlaubt korrigiert auf log2(N)+1
LWG 2150 C++98 wenn ein Iterator iter in [first, last) existiert, so dass
bool(comp(*iter, value)) ist false, std::lower_bound
konnte jeden Iterator in [iter, last)
kein Iterator nach
iter kann zurückgegeben werden

Siehe auch

findet den Bereich von Elementen, die dem gegebenen Wert entsprechen, mittels binärer Suche
(Funktionsvorlage & Algorithmusfunktionsobjekt)
teilt einen Bereich von Elementen in zwei Gruppen auf
(Funktionsvorlage & Algorithmusfunktionsobjekt)
lokalisiert den Partitionierungspunkt eines partitionierten Bereichs
(Funktionsvorlage & Algorithmusfunktionsobjekt)
findet das erste Element, das größer als der gegebene Wert ist, mittels binärer Suche
(Funktionsvorlage & Algorithmusfunktionsobjekt)
gibt einen Iterator zum ersten Element zurück, das nicht kleiner als der gegebene Schlüssel ist
(öffentliche Memberfunktion von std::set<Key,Compare,Allocator>)
gibt einen Iterator zum ersten Element zurück, das nicht kleiner als der gegebene Schlüssel ist
(öffentliche Memberfunktion von std::multiset<Key,Compare,Allocator>)
findet das erste Element, das nicht kleiner als der gegebene Wert ist, mittels binärer Suche
(Algorithmusfunktionsobjekt)