std::prev_permutation
| Definiert in Header <algorithm> |
||
| template< class BidirIt > bool prev_permutation( BidirIt first, BidirIt last ); |
(1) | (constexpr seit C++20) |
| template< class BidirIt, class Compare > bool prev_permutation( BidirIt first, BidirIt last, Compare comp ); |
(2) | (constexpr seit C++20) |
Transformiert den Bereich [first, last) in die vorherige Permutation. Gibt true zurück, wenn eine solche Permutation existiert, andernfalls transformiert der Bereich in die letzte Permutation (als ob durch std::sort gefolgt von std::reverse) 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 ValueSwappable und LegacyBidirectionalIterator erfüllen. | ||
[edit] Rückgabewert
true, wenn die neue Permutation der alten in lexikographischer Reihenfolge vorausgeht. false, wenn die erste Permutation erreicht wurde und der Bereich auf die letzte Permutation zurückgesetzt wurde.
[edit] Ausnahmen
Alle Ausnahmen, die von Iterator-Operationen oder dem Vertauschen von Elementen geworfen werden.
[edit] Komplexität
Gegeben sei N als std::distance(first, last).
| N |
| 2 |
[edit] Mögliche Implementierung
template<class BidirIt> bool prev_permutation(BidirIt first, BidirIt last) { if (first == last) return false; BidirIt i = last; if (first == --i) return false; while (1) { BidirIt i1, i2; i1 = i; if (*i1 < *--i) { i2 = last; while (!(*--i2 < *i)) ; std::iter_swap(i, i2); std::reverse(i1, last); return true; } if (i == first) { std::reverse(first, last); return false; } } } |
[edit] Anmerkungen
Im Durchschnitt über die gesamte Sequenz von Permutationen 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 sechs Permutationen des Strings "cab" in umgekehrter Reihenfolge aus.
#include <algorithm> #include <iostream> #include <string> int main() { std::string s = "cab"; do { std::cout << s << ' '; } while (std::prev_permutation(s.begin(), s.end())); std::cout << s << '\n'; }
Ausgabe
cab bca bac acb abc cba
[edit] Siehe auch
| (C++11) |
bestimmt, ob eine Sequenz eine Permutation einer anderen Sequenz ist (Funktionsvorlage) |
| erzeugt die nächstgrößere lexikographische Permutation eines Bereichs von Elementen (Funktionsvorlage) | |
| (C++20) |
erzeugt die nächstkleinere lexikographische Permutation eines Bereichs von Elementen (Algorithmus-Funktionsobjekt) |