std::ranges::is_permutation
| Definiert in Header <algorithm>
|
||
| Aufrufsignatur |
||
template< std::forward_iterator I1, std::sentinel_for<I1> S1,
std::forward_iterator I2, std::sentinel_for<I2> S2,
class Proj1 = std::identity, class Proj2 = std::identity,
std::indirect_equivalence_relation<std::projected<I1, Proj1>,
std::projected<I2, Proj2>>
Pred = ranges::equal_to >
constexpr bool
is_permutation( I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {} );
|
(1) | (seit C++20) |
template< ranges::forward_range R1, ranges::forward_range R2,
class Proj1 = std::identity, class Proj2 = std::identity,
std::indirect_equivalence_relation<
std::projected<ranges::iterator_t<R1>, Proj1>,
std::projected<ranges::iterator_t<R2>, Proj2>>
Pred = ranges::equal_to >
constexpr bool
is_permutation( R1&& r1, R2&& r2, Pred pred = {},
Proj1 proj1 = {}, Proj2 proj2 = {} );
|
(2) | (seit C++20) |
true zurück, falls es eine Permutation der Elemente im Bereich [first1, last1) gibt, die den Bereich gleich zu [first2, last2) macht (nach Anwendung der entsprechenden Projektionen Proj1, Proj2, und unter Verwendung des binären Prädikats Pred als Vergleichsfunktion). Andernfalls gibt es false zurück.r1 als ersten Quellbereich und r2 als zweiten Quellbereich, als ob ranges::begin(r1) als first1, ranges::end(r1) als last1, ranges::begin(r2) als first2 und ranges::end(r2) als last2 verwendet würden.Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithmus-Funktionsobjekte (informell als Niebloids bekannt), das heißt:
- Explizite Template-Argumentlisten können nicht angegeben werden, wenn eines von ihnen aufgerufen wird.
- Keines von ihnen ist für die argumentabhängige Suche sichtbar.
- Wenn eines von ihnen durch normale unqualifizierte Suche als Name links vom Funktionsaufrufoperator gefunden wird, wird die argumentabhängige Suche unterbunden.
Parameter
| first1, last1 | - | das Iterator-Sentinel-Paar, das den ersten Bereich von Elementen definiert |
| first2, last2 | - | das Iterator-Sentinel-Paar, das den zweiten Bereich von Elementen definiert |
| r1 | - |
der erste
range
der Elemente
|
| r2 | - |
der zweite
range
der Elemente
|
| pred | - | Prädikat, das auf die projizierten Elemente angewendet wird |
| proj1 | - | Projektion, die auf die Elemente im ersten Bereich angewendet wird |
| proj2 | - | Projektion, die auf die Elemente im zweiten Bereich angewendet wird |
Rückgabewert
true
falls der Bereich
[
first1
,
last1
)
eine Permutation des Bereichs
[
first2
,
last2
)
ist.
Komplexität
Höchstens O(N 2 ) Anwendungen des Prädikats und jeder Projektion, oder genau N falls die Sequenzen bereits gleich sind, wobei N ist ranges:: distance ( first1, last1 ) . Allerdings falls ranges:: distance ( first1, last1 ) ! = ranges:: distance ( first2, last2 ) , werden keine Anwendungen des Prädikats und der Projektionen durchgeführt.
Hinweise
Die Permutation -Relation ist eine Äquivalenzrelation .
Die
ranges::is_permutation
kann im Testing verwendet werden, z.B. um die Korrektheit von umordnenden Algorithmen wie Sortieren, Mischen, Partitionieren zu überprüfen. Wenn
p
eine ursprüngliche Sequenz ist und
q
eine "mutierte" Sequenz, dann bedeutet
ranges
::
is_permutation
(
p, q
)
==
true
, dass
q
aus "denselben" Elementen (möglicherweise permutiert) besteht wie
p
.
Mögliche Implementierung
struct is_permutation_fn { template<std::forward_iterator I1, std::sentinel_for<I1> S1, std::forward_iterator I2, std::sentinel_for<I2> S2, class Proj1 = std::identity, class Proj2 = std::identity, std::indirect_equivalence_relation<std::projected<I1, Proj1>, std::projected<I2, Proj2>> Pred = ranges::equal_to> constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { // gemeinsamen Präfix überspringen auto ret = std::ranges::mismatch(first1, last1, first2, last2, std::ref(pred), std::ref(proj1), std::ref(proj2)); first1 = ret.in1, first2 = ret.in2; // über den Rest iterieren, zählen wie oft jedes Element vorkommt // aus [first1, last1) erscheint in [first2, last2) for (auto i {first1}; i != last1; ++i) { const auto i_proj {std::invoke(proj1, *i)}; auto i_cmp = [&]<typename T>(T&& t) { return std::invoke(pred, i_proj, std::forward<T>(t)); }; if (i != ranges::find_if(first1, i, i_cmp, proj1)) continue; // dieser *i wurde geprüft if (const auto m {ranges::count_if(first2, last2, i_cmp, proj2)}; m == 0 or m != ranges::count_if(i, last1, i_cmp, proj1)) return false; } return true; } template<ranges::forward_range R1, ranges::forward_range R2, class Proj1 = std::identity, class Proj2 = std::identity, std::indirect_equivalence_relation< std::projected<ranges::iterator_t<R1>, Proj1>, std::projected<ranges::iterator_t<R2>, Proj2>> Pred = ranges::equal_to> constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const { return (*this)(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), std::move(pred), std::move(proj1), std::move(proj2)); } }; inline constexpr is_permutation_fn is_permutation {}; |
Beispiel
#include <algorithm> #include <array> #include <cmath> #include <iostream> #include <ranges> auto& operator<<(auto& os, std::ranges::forward_range auto const& v) { os << "{ "; for (const auto& e : v) os << e << ' '; return os << "}"; } int main() { static constexpr auto r1 = {1, 2, 3, 4, 5}; static constexpr auto r2 = {3, 5, 4, 1, 2}; static constexpr auto r3 = {3, 5, 4, 1, 1}; static_assert( std::ranges::is_permutation(r1, r1) && std::ranges::is_permutation(r1, r2) && std::ranges::is_permutation(r2, r1) && std::ranges::is_permutation(r1.begin(), r1.end(), r2.begin(), r2.end())); std::cout << std::boolalpha << "is_permutation(" << r1 << ", " << r2 << "): " << std::ranges::is_permutation(r1, r2) << '\n' << "is_permutation(" << r1 << ", " << r3 << "): " << std::ranges::is_permutation(r1, r3) << '\n' << "is_permutation with custom predicate and projections: " << std::ranges::is_permutation( std::array {-14, -11, -13, -15, -12}, // 1st range std::array {'F', 'E', 'C', 'B', 'D'}, // 2nd range [](int x, int y) { return abs(x) == abs(y); }, // predicate [](int x) { return x + 10; }, // projection for 1st range [](char y) { return int(y - 'A'); }) // projection for 2nd range << '\n'; }
Ausgabe:
is_permutation({ 1 2 3 4 5 }, { 3 5 4 1 2 }): true
is_permutation({ 1 2 3 4 5 }, { 3 5 4 1 1 }): false
is_permutation with custom predicate and projections: true
Siehe auch
(C++20) |
erzeugt die nächste lexikografisch größere Permutation eines Bereichs von Elementen (Algorithmusfunktionsobjekt) |
(C++20) |
erzeugt die nächste lexikografisch kleinere Permutation eines Bereichs von Elementen (Algorithmusfunktionsobjekt) |
(C++11) |
bestimmt, ob eine Sequenz eine Permutation einer anderen Sequenz ist (Funktionstemplate) |
| erzeugt die nächste lexikografisch größere Permutation eines Bereichs von Elementen (Funktionstemplate & Algorithmusfunktionsobjekt) | |
(C++20) |
|
| erzeugt die nächste lexikografisch kleinere Permutation eines Bereichs von Elementen (Funktionstemplate & Algorithmusfunktionsobjekt) | |
(C++20) |
|
(C++20) |
spezifiziert, dass eine Relation eine Äquivalenzrelation auferlegt (Konzept) |