Namespaces
Variants

std:: equal_range

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
equal_range
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Definiert im 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 [ first , last ) 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 irgendein Element elem von [ first , last ) impliziert bool ( elem < value ) nicht ! bool ( value < elem ) .
  • Die Elemente elem von [ first , last ) sind nicht bezüglich der Ausdrücke bool ( elem < value ) und ! bool ( value < elem ) partitioniert .
(bis C++20)

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

(seit C++20)
2) Die Äquivalenz wird unter Verwendung von comp überprü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 irgendein Element elem von [ first , last ) , bool ( comp ( elem, value ) ) impliziert nicht ! bool ( comp ( value, elem ) ) .
  • Die Elemente elem von [ first , last ) sind nicht partitioniert bezüglich der Ausdrücke bool ( comp ( elem, value ) ) und ! bool ( comp ( value, elem ) ) .

Inhaltsverzeichnis

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 äquivalent zu Folgendem sein:

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

Obwohl die Signatur nicht const & benötigt, 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 können (daher ist Type1 & nicht erlaubt , ebenso wenig wie Type1 , es sei denn, für Type1 ist eine Verschiebung äquivalent zu einer Kopie (seit C++11) ).
Die Typen Type1 und Type2 müssen so beschaffen sein, dass ein Objekt vom Typ T implizit sowohl in Type1 als auch in Type2 konvertiert werden kann, und ein Objekt vom Typ ForwardIt dereferenziert und dann implizit sowohl in Type1 als auch in Type2 konvertiert werden kann. ​

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

Rückgabewert

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

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

Komplexität

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

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

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

Hinweise

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

Zusätzlich zu den Anforderungen von std::lower_bound und std::upper_bound erfordert std::equal_range außerdem, dass operator < oder comp asymmetrisch sind (d.h., a < b und b < a immer unterschiedliche Ergebnisse liefern).

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

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

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

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)

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 (strikte schwache Ordnung erforderlich)
nur Partitionierung erforderlich;
heterogene Vergleiche erlaubt
LWG 384 C++98 maximal 2log 2 (N)+1 Vergleiche
erlaubt, was nicht implementierbar ist [1]
korrigiert auf 2log 2 (N)+O(1)
  1. Die Anwendung von equal_range auf einen Einzelelement-Bereich erfordert 2 Vergleiche, aber gemäß der Komplexitätsanforderung ist höchstens 1 Vergleich zulässig.

Siehe auch

gibt einen Iterator zum ersten Element zurück, das nicht kleiner als der gegebene Wert ist
(Funktions-Template)
gibt einen Iterator zum ersten Element zurück, das größer als ein bestimmter Wert ist
(Funktions-Template)
bestimmt, ob ein Element in einem teilweise geordneten Bereich existiert
(Funktions-Template)
teilt einen Elementbereich in zwei Gruppen auf
(Funktions-Template)
bestimmt, ob zwei Elementmengen identisch sind
(Funktions-Template)
gibt den Bereich der Elemente zurück, die einem spezifischen Schlüssel entsprechen
(öffentliche Elementfunktion von std::set<Key,Compare,Allocator> )
gibt den Bereich der Elemente zurück, die einem spezifischen Schlüssel entsprechen
(öffentliche Elementfunktion von std::multiset<Key,Compare,Allocator> )
gibt den Bereich der Elemente zurück, die einem spezifischen Schlüssel entsprechen
(Algorithmus-Funktionsobjekt)