Namespaces
Variants

std::ranges::is_permutation

Depuis fr.cppreference.net
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur les intervalles (C++20)
Algorithmes contraints, par ex. ranges::copy, ranges::sort, ...
Opérations de séquence non modifiantes    
Opérations par lots
(C++17)
Opérations de recherche
Opérations de séquence modifiantes
Opérations de copie
(C++11)
(C++11)
Opérations d'échange
Opérations de transformation
Opérations de génération
Opérations de suppression
Opérations de changement d'ordre
(jusqu'à C++17)(C++11)
(C++20)(C++20)
Opérations d'échantillonnage
(C++17)

Opérations de tri et opérations connexes
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur des intervalles partitionnés)
Opérations ensemblistes (sur des intervalles triés)
Opérations de fusion (sur des intervalles triés)
Opérations de tas
Opérations de minimum/maximum
(C++11)
(C++17)
Opérations de comparaison lexicographique
Opérations de permutation


 
Algorithmes contraints
Tous les noms de ce menu appartiennent à l'espace de noms std::ranges
Opérations de séquence non modifiantes
Opérations de séquence modifiantes
Opérations de partitionnement
Opérations de tri
Opérations de recherche binaire (sur des intervalles triés)
       
       
Opérations ensemblistes (sur des intervalles triés)
Opérations de tas
Opérations de minimum/maximum
       
       
Opérations de permutation
Opérations de pliage
Opérations sur le stockage non initialisé
Types de retour
 
Défini dans l'en-tête <algorithm>
Signature d'appel
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) (depuis 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) (depuis C++20)
1) Renvoie true s'il existe une permutation des éléments de l'intervalle [first1last1) qui rend l'intervalle égal à [first2last2) (après application des projections correspondantes Proj1, Proj2, et en utilisant le prédicat binaire Pred comme comparateur). Sinon, renvoie false.
2) Identique à (1), mais utilise r1 comme première intervalle source et r2 comme seconde intervalle source, comme si on utilisait ranges::begin(r1) comme first1, ranges::end(r1) comme last1, ranges::begin(r2) comme first2, et ranges::end(r2) comme last2.

Les entités de type fonction décrites sur cette page sont des objets de fonction d'algorithme (informellement appelés niebloids), c'est-à-dire :

Paramètres

first1, last1 - la paire itérateur-sentinelle définissant la première plage d'éléments
first2, last2 - la paire itérateur-sentinelle définissant la seconde plage d'éléments
r1 - la première range des éléments
r2 - la seconde range des éléments
pred - prédicat à appliquer aux éléments projetés
proj1 - projection à appliquer aux éléments de la première plage
proj2 - projection à appliquer aux éléments de la seconde plage

Valeur de retour

true si la plage [ first1 , last1 ) est une permutation de la plage [ first2 , last2 ) .

Complexité

Au plus O(N 2 ) applications du prédicat et de chaque projection, ou exactement N si les séquences sont déjà égales, où N est ranges:: distance ( first1, last1 ) . Cependant si ranges:: distance ( first1, last1 ) ! = ranges:: distance ( first2, last2 ) , aucune application du prédicat et des projections n'est effectuée.

Notes

La permutation est une relation d'équivalence .

La ranges::is_permutation peut être utilisée dans les tests, par exemple pour vérifier l'exactitude des algorithmes de réarrangement tels que le tri, le mélange, la partition. Si p est une séquence originale et q est une séquence "mutée", alors ranges :: is_permutation ( p, q ) == true signifie que q est constituée des "mêmes" éléments (éventuellement permutés) que p .

Implémentation possible

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
    {
        // ignorer le préfixe commun
        auto ret = std::ranges::mismatch(first1, last1, first2, last2,
                                         std::ref(pred), std::ref(proj1), std::ref(proj2));
        first1 = ret.in1, first2 = ret.in2;
        // itérer sur le reste, en comptant combien de fois chaque élément
        // de [first1, last1) apparaît dans [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; // ce *i a été vérifié
            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 {};

Exemple

#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';
}

Sortie :

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

Voir aussi

génère la permutation lexicographique suivante plus grande d'une plage d'éléments
(objet fonction d'algorithme)
génère la permutation lexicographique suivante plus petite d'une plage d'éléments
(objet fonction d'algorithme)
détermine si une séquence est une permutation d'une autre séquence
(modèle de fonction)
génère la permutation lexicographique suivante plus grande d'une plage d'éléments
(modèle de fonction & objet fonction d'algorithme)
génère la permutation lexicographique suivante plus petite d'une plage d'éléments
(modèle de fonction & objet fonction d'algorithme)
spécifie qu'une relation impose une relation d'équivalence
(concept)