Namensräume
Varianten
Aktionen

std::equal_range

Von cppreference.com
< cpp‎ | algorithm
 
 
Algorithmenbibliothek
Beschränkte Algorithmen und Algorithmen für Bereiche (C++20)
Beschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Ausführungsrichtlinien (C++17)
Nicht-modifizierende Sequenzoperationen
Stapeloperationen
(C++17)
Suchoperationen
(C++11)                (C++11)(C++11)

Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Ordnungsändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
equal_range
Mengenoperationen (auf sortierten Bereichen)
Zusammenführungsoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikographische Vergleichsoperationen
Permutationsoperationen
C-Bibliothek
Numerische Operationen
Operationen auf uninitialisiertem Speicher
 
Definiert in Header <algorithm>
(1)
template< class ForwardIt, class T >

std::pair<ForwardIt, ForwardIt>

    equal_range( ForwardIt first, ForwardIt last, const T& value );
(constexpr seit C++20)
(bis C++26)
template< class ForwardIt, class T = typename std::iterator_traits

                                         <ForwardIt>::value_type >
constexpr std::pair<ForwardIt, ForwardIt>

    equal_range( ForwardIt first, ForwardIt last, const T& value );
(seit C++26)
(2)
template< class ForwardIt, class T, class Compare >

std::pair<ForwardIt, ForwardIt>
    equal_range( ForwardIt first, ForwardIt last,

                 const T& value, Compare comp );
(constexpr seit C++20)
(bis C++26)
template< class ForwardIt, class T = typename std::iterator_traits

                                         <ForwardIt>::value_type,
          class Compare >
constexpr std::pair<ForwardIt, ForwardIt>
    equal_range( ForwardIt first, ForwardIt last,

                 const T& value, Compare comp );
(seit C++26)

Gibt einen Bereich zurück, der alle Elemente enthält, die äquivalent zu value im partitionierten Bereich [firstlast) sind.

1) Die Äquivalenz wird mittels operator< geprüft.

Gibt die Ergebnisse von std::lower_bound(first, last, value) und std::upper_bound(first, last, value) zurück.

Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert

  • Für jedes Element elem aus [firstlast) impliziert bool(elem < value) nicht !bool(value < elem).
  • Die Elemente elem aus [firstlast) sind nicht bezüglich der Ausdrücke bool(elem < value) und !bool(value < elem) partitioniert.
(bis C++20)

Entspricht std::equal_range(first, last, value, std::less{}).

(seit C++20)
2) Die Äquivalenz wird mittels comp geprüft.
Gibt die Ergebnisse von std::lower_bound(first, last, value, comp) und std::upper_bound(first, last, value, comp) zurück.
Wenn eine der folgenden Bedingungen erfüllt ist, ist das Verhalten undefiniert
  • Für jedes Element elem aus [firstlast) impliziert bool(comp(elem, value)) nicht !bool(comp(value, elem)).
  • Die Elemente elem aus [firstlast) sind nicht bezüglich der Ausdrücke bool(comp(elem, value)) und !bool(comp(value, elem)) partitioniert.

Inhalt

[edit] Parameter

first, last - das Iterator-Paar, das den partitionierten Bereich der zu untersuchenden Elemente definiert
value - Wert, mit dem die Elemente verglichen werden sollen
comp - Binäres Prädikat, das **wahr** zurückgibt, wenn das erste Argument vor dem zweiten geordnet ist.

Die Signatur der Prädikatfunktion sollte äquivalent zur folgenden sein:

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

Obwohl die Signatur nicht zwingend const & haben muss, darf die Funktion die ihr übergebenen Objekte nicht modifizieren und muss alle Werte vom Typ (möglicherweise const) Type1 und Type2 unabhängig von der Wertkategorie akzeptieren können (daher ist Type1 & nicht erlaubt, ebenso wenig wie Type1, es sei denn, für Type1 ist eine Verschiebung gleichbedeutend mit einer Kopie(seit C++11)).
Die Typen Type1 und Type2 müssen so beschaffen sein, dass ein Objekt vom Typ T implizit in sowohl Type1 als auch Type2 konvertiert werden kann, und ein Objekt vom Typ ForwardIt dereferenziert und dann implizit in sowohl Type1 als auch Type2 konvertiert werden kann. ​

Typanforderungen
-
ForwardIt muss die Anforderungen von LegacyForwardIterator erfüllen.
-
Compare muss die Anforderungen an ein Binäres Prädikat erfüllen. Es muss nicht Compare erfüllen.

[edit] Rückgabewert

Ein std::pair, das ein Paar von Iteratoren enthält, wobei

  • first ein Iterator zum ersten Element des Bereichs [firstlast) ist, das nicht vor value geordnet ist (oder last, wenn kein solches Element gefunden wird), und
  • second ein Iterator zum ersten Element des Bereichs [firstlast) ist, das nach value geordnet ist (oder last, wenn kein solches Element gefunden wird).

[edit] Komplexität

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

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

Wenn jedoch ForwardIt kein LegacyRandomAccessIterator ist, ist die Anzahl der Iterator-Inkremente linear in N. Insbesondere sind Iteratoren von std::set und std::multiset keine Random-Access-Iteratoren, daher sollten deren Memberfunktionen std::set::equal_range (bzw. std::multiset::equal_range) bevorzugt werden.

[edit] Anmerkungen

Obwohl std::equal_range nur erfordert, dass [firstlast) partitioniert ist, wird dieser Algorithmus normalerweise in Fällen verwendet, in denen [firstlast) sortiert ist, sodass die binäre Suche für jedes value gültig ist.

Zusätzlich zu den Anforderungen von std::lower_bound und std::upper_bound erfordert std::equal_range auch, dass operator< oder comp asymmetrisch ist (d. h., a < b und b < a haben immer unterschiedliche Ergebnisse).

Daher können die Zwischenergebnisse der binären Suche von std::lower_bound und std::upper_bound geteilt werden. Zum Beispiel kann das Ergebnis des Aufrufs von std::lower_bound als Argument für first im Aufruf von std::upper_bound verwendet werden.

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

[edit] Mögliche Implementierung

equal_range (1)
template<class ForwardIt,
         class T = typename std::iterator_traits<ForwardIt>::value_type>
constexpr std::pair<ForwardIt, ForwardIt> 
    equal_range(ForwardIt first, ForwardIt last, const T& value)
{
    return std::equal_range(first, last, value, std::less{});
}
equal_range (2)
template<class ForwardIt,
         class T = typename std::iterator_traits<ForwardIt>::value_type,
         class Compare>
constexpr std::pair<ForwardIt, ForwardIt>
    equal_range(ForwardIt first, ForwardIt last, const T& value, Compare comp)
{
    return std::make_pair(std::lower_bound(first, last, value, comp),
                          std::upper_bound(first, last, value, comp));
}

[edit] Beispiel

#include <algorithm>
#include <complex>
#include <iostream>
#include <vector>
 
struct S
{
    int number;
    char name;
    // note: name is ignored by this comparison operator
    bool operator<(const S& s) const { return number < s.number; }
};
 
struct Comp
{
    bool operator()(const S& s, int i) const { return s.number < i; }
    bool operator()(int i, const S& s) const { return i < s.number; }
};
 
int main()
{
    // note: not ordered, only partitioned w.r.t. S defined below
    const std::vector<S> vec{{1, 'A'}, {2, 'B'}, {2, 'C'},
                             {2, 'D'}, {4, 'G'}, {3, 'F'}};
    const S value{2, '?'};
 
    std::cout << "Compare using S::operator<(): ";
    const auto p = std::equal_range(vec.begin(), vec.end(), value);
 
    for (auto it = p.first; it != p.second; ++it)
        std::cout << it->name << ' ';
    std::cout << '\n';
 
    std::cout << "Using heterogeneous comparison: ";
    const auto p2 = std::equal_range(vec.begin(), vec.end(), 2, Comp{});
 
    for (auto it = p2.first; it != p2.second; ++it)
        std::cout << it->name << ' ';
    std::cout << '\n';
 
    using CD = std::complex<double>;
    std::vector<CD> nums{{1, 0}, {2, 2}, {2, 1}, {3, 0}, {3, 1}};
    auto cmpz = [](CD x, CD y) { return x.real() < y.real(); };
    #ifdef __cpp_lib_algorithm_default_value_type
        auto p3 = std::equal_range(nums.cbegin(), nums.cend(), {2, 0}, cmpz);
    #else
        auto p3 = std::equal_range(nums.cbegin(), nums.cend(), CD{2, 0}, cmpz);
    #endif
 
    for (auto it = p3.first; it != p3.second; ++it)
        std::cout << *it << ' ';
    std::cout << '\n';
}

Ausgabe

Compare using S::operator<(): B C D 
Using heterogeneous comparison: B C D
(2,2) (2, 1)

[edit] Fehlerberichte

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

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
LWG 270 C++98 Compare musste Compare erfüllen und T musste
LessThanComparable sein (starke schwache Ordnung erforderlich)
nur eine Partitionierung ist erforderlich;
heterogene Vergleiche zulässig
LWG 384 C++98 höchstens 2log2(N)+1 Vergleiche
waren erlaubt, was nicht implementierbar ist[1]
korrigiert zu 2log2(N)+O(1)
  1. Das Anwenden von equal_range auf einen Bereich mit einem Element erfordert 2 Vergleiche, aber die Komplexitätsanforderung erlaubt höchstens 1 Vergleich.

[edit] Siehe auch

Gibt einen Iterator zum ersten Element zurück, das nicht kleiner als der gegebene Wert ist
(Funktionstemplate) [edit]
Gibt einen Iterator zum ersten Element zurück, das *größer* als ein bestimmter Wert ist
(Funktionstemplate) [edit]
Stellt fest, ob ein Element in einem teilweise geordneten Bereich vorhanden ist
(Funktionstemplate) [edit]
Teilt einen Bereich von Elementen in zwei Gruppen auf
(Funktionstemplate) [edit]
Bestimmt, ob zwei Elementmengen gleich sind
(Funktionstempelat) [edit]
gibt den Bereich von Elementen zurück, die einem bestimmten Schlüssel entsprechen
(public member function of std::set<Key,Compare,Allocator>) [edit]
gibt den Bereich von Elementen zurück, die einem bestimmten Schlüssel entsprechen
(public member function of std::multiset<Key,Compare,Allocator>) [edit]
gibt den Bereich von Elementen zurück, die einem bestimmten Schlüssel entsprechen
(Algorithmus-Funktionsobjekt)[edit]