std::next_permutation
| Definiert in Header <algorithm> |
||
| template< class BidirIt > bool next_permutation( BidirIt first, BidirIt last ); |
(1) | (constexpr seit C++20) |
| template< class BidirIt, class Compare > bool next_permutation( BidirIt first, BidirIt last, Compare comp ); |
(2) | (constexpr seit C++20) |
Permutiert den Bereich [first, last) in die nächste Permutation. Gibt true zurück, wenn eine solche "nächste Permutation" existiert; andernfalls transformiert sie den Bereich in die lexikographisch erste Permutation (als ob durch std::sort) und gibt false zurück.
Wenn der Typ von *first nicht Swappable ist(bis C++11)BidirIt nicht ValueSwappable ist(seit C++11), ist das Verhalten undefiniert.
Inhalt |
[edit] Parameter
| first, last | - | das Iteratorenpaar, das den Bereich der zu permutierenden Elemente definiert |
| comp | - | Ein Vergleichsfunktions-Objekt (d.h. ein Objekt, das die Anforderungen an Compare erfüllt), das true zurückgibt, wenn das erste Argument *weniger* als das zweite ist. Die Signatur der Vergleichsfunktion sollte äquivalent zu Folgendem sein bool cmp(const Type1& a, const Type2& b); Obwohl die Signatur nicht const& haben muss, darf die Funktion die übergebenen Objekte nicht modifizieren und muss alle Werte vom Typ (möglicherweise const) |
| Typanforderungen | ||
-BidirIt muss die Anforderungen von LegacyBidirectionalIterator erfüllen. | ||
[edit] Rückgabewert
true, wenn die neue Permutation lexikographisch größer als die alte ist. false, wenn die letzte Permutation erreicht wurde und der Bereich auf die erste Permutation zurückgesetzt wurde.
[edit] Komplexität
Gegeben sei N als std::distance(first, last).
| N |
| 2 |
[edit] Ausnahmen
Alle Ausnahmen, die von Iterator-Operationen oder dem Vertauschen von Elementen geworfen werden.
[edit] Mögliche Implementierung
template<class BidirIt> bool next_permutation(BidirIt first, BidirIt last) { auto r_first = std::make_reverse_iterator(last); auto r_last = std::make_reverse_iterator(first); auto left = std::is_sorted_until(r_first, r_last); if (left != r_last) { auto right = std::upper_bound(r_first, left, *left); std::iter_swap(left, right); } std::reverse(left.base(), last); return left != r_last; } |
[edit] Anmerkungen
Durchschnittlich über die gesamte Sequenz von Permutationen hinweg verwenden typische Implementierungen etwa 3 Vergleiche und 1,5 Vertauschungen pro Aufruf.
Implementierungen (z.B. MSVC STL) können Vektorisierung aktivieren, wenn der Iteratortyp LegacyContiguousIterator erfüllt und das Vertauschen seines Wertetyps weder eine nicht-triviale spezielle Member-Funktion noch eine über ADL gefundene swap-Funktion aufruft.
[edit] Beispiel
Der folgende Code gibt alle drei Permutationen des Strings "aba" aus.
#include <algorithm> #include <iostream> #include <string> int main() { std::string s = "aba"; do { std::cout << s << '\n'; } while (std::next_permutation(s.begin(), s.end())); std::cout << s << '\n'; }
Ausgabe
aba baa aab
[edit] Siehe auch
| (C++11) |
bestimmt, ob eine Sequenz eine Permutation einer anderen Sequenz ist (Funktionsvorlage) |
| erzeugt die nächstkleinere lexikographische Permutation eines Bereichs von Elementen (Funktionsvorlage) | |
| (C++20) |
erzeugt die nächstgrößere lexikographische Permutation eines Bereichs von Elementen (Algorithmus-Funktionsobjekt) |