Namensräume
Varianten
Aktionen

std::nth_element

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
(C++11)
nth_element

Binäre Suchoperationen
(auf partitionierten Bereichen)
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>
template< class RandomIt >
void nth_element( RandomIt first, RandomIt nth, RandomIt last );
(1) (constexpr seit C++20)
template< class ExecutionPolicy, class RandomIt >

void nth_element( ExecutionPolicy&& policy,

                  RandomIt first, RandomIt nth, RandomIt last );
(2) (seit C++17)
template< class RandomIt, class Compare >

void nth_element( RandomIt first, RandomIt nth, RandomIt last,

                  Compare comp );
(3) (constexpr seit C++20)
template< class ExecutionPolicy, class RandomIt, class Compare >

void nth_element( ExecutionPolicy&& policy,
                  RandomIt first, RandomIt nth, RandomIt last,

                  Compare comp );
(4) (seit C++17)

nth_element ordnet Elemente in [firstlast) neu an, sodass nach der Neuanordnung

  • Das von nth zeigende Element wird zu dem Element geändert, das an dieser Position stehen würde, wenn [firstlast) sortiert wäre.
  • Für jeden Iterator i in [firstnth) und jeden Iterator j in [nthlast) ist die folgende Bedingung erfüllt:
1,2) bool(*j < *i)(bis C++20)std::less{}(*j, *i)(seit C++20) ist false.
3,4) bool(comp(*j, *i)) ist false.


1) Elemente werden hypothetisch nach operator<(bis C++20)std::less{}(seit C++20) sortiert.
3) Elemente werden hypothetisch nach comp sortiert.
2,4) Dasselbe wie (1,3), aber ausgeführt gemäß policy.
Diese Überladungen nehmen an der Auflösungsauflösung teil, nur wenn alle folgenden Bedingungen erfüllt sind

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> ist true.

(bis C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> ist true.

(seit C++20)

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

(bis C++11)
(seit C++11)

Inhalt

[edit] Parameter

first, last - das Iterator-Paar, das den Bereich der Elemente für die Teilsortierung definiert
nth - Random-Access-Iterator, der den Sortierungspartitionspunkt definiert
policy - die Ausführungsrichtlinie, die verwendet werden soll
comp - Vergleichsfunktions-Objekt (d.h. ein Objekt, das die Anforderungen an Compare erfüllt), das ​true zurückgibt, wenn das erste Argument *weniger* (d.h. *vorher*) als das zweite geordnet ist.

Die Signatur der Vergleichsfunktion sollte äquivalent zu Folgendem sein

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

Obwohl die Signatur nicht unbedingt const& haben muss, darf die Funktion die übergebenen Objekte nicht verändern und muss in der Lage sein, alle Werte vom Typ (möglicherweise const) Type1 und Type2 unabhängig von der Wertkategorie zu akzeptieren (daher ist Type1& nicht erlaubt, ebenso wenig Type1, es sei denn, für Type1 ist ein Move äquivalent zu einem Kopieren(since C++11)).
Die Typen Type1 und Type2 müssen so beschaffen sein, dass ein Objekt des Typs RandomIt dereferenziert und dann implizit in beide konvertiert werden kann. ​

Typanforderungen
-
RandomIt muss die Anforderungen an einen LegacyRandomAccessIterator erfüllen.
-
Compare muss die Anforderungen an Compare erfüllen.

[edit] Komplexität

Gegeben N als last - first

1) O(N) Vergleiche mit operator<(bis C++20)std::less{}(seit C++20) im Durchschnitt.
2) O(N) Vergleiche mit operator<(bis C++20)std::less{}(seit C++20) und O(N·log(N)) Vertauschungen.
3) O(N) Anwendungen des Komparators comp im Durchschnitt.
4) O(N) Anwendungen des Komparators comp und O(N·log(N)) Vertauschungen.

[edit] Ausnahmen

Die Überladungen mit einem Template-Parameter namens ExecutionPolicy berichten Fehler wie folgt

  • Wenn die Ausführung einer Funktion, die als Teil des Algorithmus aufgerufen wird, eine Ausnahme auslöst und ExecutionPolicy eine der Standardrichtlinien ist, wird std::terminate aufgerufen. Für jede andere ExecutionPolicy ist das Verhalten implementierungsabhängig.
  • Wenn dem Algorithmus der Speicher zur Neuzuweisung fehlt, wird std::bad_alloc ausgelöst.

[edit] Mögliche Implementierung

Siehe auch die Implementierungen in libstdc++, libc++ und MSVC STL.

[edit] Hinweise

Der verwendete Algorithmus ist typischerweise Introselect, obwohl auch andere Selection-Algorithmen mit geeigneter durchschnittlicher Komplexität zulässig sind.

[edit] Beispiel

#include <algorithm>
#include <cassert>
#include <functional>
#include <iostream>
#include <numeric>
#include <vector>
 
void printVec(const std::vector<int>& vec)
{
    std::cout << "v = {";
    for (char sep[]{0, ' ', 0}; const int i : vec)
        std::cout << sep << i, sep[0] = ',';
    std::cout << "};\n";
}
 
int main()
{
    std::vector<int> v{5, 10, 6, 4, 3, 2, 6, 7, 9, 3};
    printVec(v);
 
    auto m = v.begin() + v.size() / 2;
    std::nth_element(v.begin(), m, v.end());
    std::cout << "\nThe median is " << v[v.size() / 2] << '\n';
    // The consequence of the inequality of elements before/after the Nth one:
    assert(std::accumulate(v.begin(), m, 0) < std::accumulate(m, v.end(), 0));
    printVec(v);
 
    // Note: comp function changed
    std::nth_element(v.begin(), v.begin() + 1, v.end(), std::greater{});
    std::cout << "\nThe second largest element is " << v[1] << '\n';
    std::cout << "The largest element is " << v[0] << '\n';
    printVec(v);
}

Mögliche Ausgabe

v = {5, 10, 6, 4, 3, 2, 6, 7, 9, 3};
 
The median is 6
v = {3, 2, 3, 4, 5, 6, 10, 7, 9, 6};
 
The second largest element is 9
The largest element is 10
v = {10, 9, 6, 7, 6, 3, 5, 4, 3, 2};

[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 2150 C++98 nach der Neuanordnung war nur ein Element vor nth
erforderlich, nicht größer zu sein als ein Element nach nth
korrigierte die
Anforderung
LWG 2163 C++98 Überladung (1) verwendete operator> zum Vergleichen der Elemente geändert zu operator<
P0896R4 C++98 [firstnth) und [nthlast)
waren nicht als gültige Bereiche erforderlich
das Verhalten ist undefiniert
wenn einer von ihnen ungültig ist

[edit] Siehe auch

Gibt das größte Element in einem Bereich zurück
(Funktionstemplate) [edit]
gibt das kleinste Element in einem Bereich zurück
(Funktionsvorlage) [editieren]
Kopiert und sortiert einen Bereich von Elementen teilweise
(Funktionstemplate) [edit]
Sortiert einen Bereich von Elementen und behält dabei die Reihenfolge zwischen gleichen Elementen bei
(Funktionstemplate) [edit]
Sortiert einen Bereich aufsteigend
(Funktionstemplate) [edit]
Sortiert den gegebenen Bereich teilweise, so dass er durch das gegebene Element partitioniert wird
(Algorithmus-Funktionsobjekt)[edit]