Namespaces
Variants

std::ranges:: next_permutation, std::ranges:: next_permutation_result

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
Constrained algorithms
All names in this menu belong to namespace std::ranges
Non-modifying sequence operations
Modifying sequence operations
Partitioning operations
Sorting operations
Binary search operations (on sorted ranges)
Set operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Permutation operations
Fold operations
Operations on uninitialized storage
Return types
Défini dans l'en-tête <algorithm>
Signature d'appel
template < std:: bidirectional_iterator I, std:: sentinel_for < I > S,

class Comp = ranges:: less , class Proj = std:: identity >
requires std:: sortable < I, Comp, Proj >
constexpr next_permutation_result < I >

next_permutation ( I first, S last, Comp comp = { } , Proj proj = { } ) ;
(1) (depuis C++20)
template < ranges:: bidirectional_range R, class Comp = ranges:: less ,

class Proj = std:: identity >
requires std:: sortable < ranges:: iterator_t < R > , Comp, Proj >
constexpr next_permutation_result < ranges:: borrowed_iterator_t < R >>

next_permutation ( R && r, Comp comp = { } , Proj proj = { } ) ;
(2) (depuis C++20)
Type auxiliaire
template < class I >
using next_permutation_result = ranges:: in_found_result < I > ;
(3) (depuis C++20)
1) Transforme la plage [ first , last ) en la permutation suivante, où l'ensemble de toutes les permutations est ordonné lexicographiquement par rapport à l'objet fonction de comparaison binaire comp et l'objet fonction de projection proj . Retourne { last, true } si une telle "permutation suivante" existe ; sinon transforme la plage en la première permutation lexicographique comme si par ranges:: sort ( first, last, comp, proj ) , et retourne { last, false } .
2) Identique à (1) , mais utilise r comme plage source, comme si on utilisait ranges:: begin ( r ) comme first , et ranges:: end ( r ) comme last .

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

Table des matières

Paramètres

first, last - la paire itérateur-sentinelle définissant la plage des éléments à permuter
r - la range des éléments à permuter
comp - l'objet-fonction de comparaison FunctionObject qui renvoie true si le premier argument est inférieur au second
proj - projection à appliquer aux éléments

Valeur de retour

1) ranges :: next_permutation_result < I > { last, true } si la nouvelle permutation est lexicographiquement supérieure à l'ancienne. ranges :: next_permutation_result < I > { last, false } si la dernière permutation a été atteinte et que la plage a été réinitialisée à la première permutation.
2) Identique à (1) sauf que le type de retour est ranges :: next_permutation_result < ranges:: borrowed_iterator_t < R >> .

Exceptions

Toute exception levée par les opérations d'itérateur ou l'échange d'éléments.

Complexité

Au maximum N / 2 échanges, où N est ranges:: distance ( first, last ) dans le cas (1) ou ranges:: distance ( r ) dans le cas (2) . En moyenne sur l'ensemble de la séquence de permutations, les implémentations typiques utilisent environ 3 comparaisons et 1,5 échanges par appel.

Notes

Les implémentations (par exemple MSVC STL ) peuvent activer la vectorisation lorsque le type d'itérateur modélise contiguous_iterator et que l'échange de son type de valeur n'appelle ni fonction membre spéciale non triviale ni ADL -trouvée swap .

Implémentation possible

struct next_permutation_fn
{
    template<std::bidirectional_iterator I, std::sentinel_for<I> S,
             class Comp = ranges::less, class Proj = std::identity>
    requires std::sortable<I, Comp, Proj>
    constexpr ranges::next_permutation_result<I>
        operator()(I first, S last, Comp comp = {}, Proj proj = {}) const
    {
        // vérifier que la séquence a au moins deux éléments
        if (first == last)
            return {std::move(first), false};
        I i_last{ranges::next(first, last)};
        I i{i_last};
        if (first == --i)
            return {std::move(i_last), false};
        // boucle principale de "permutation"
        for (;;)
        {
            I i1{i};
            if (std::invoke(comp, std::invoke(proj, *--i), std::invoke(proj, *i1)))
            {
                I j{i_last};
                while (!std::invoke(comp, std::invoke(proj, *i), std::invoke(proj, *--j)))
                {}
                std::iter_swap(i, j);
                std::reverse(i1, i_last);
                return {std::move(i_last), true};
            }
            // l'espace de "permutation" est épuisé
            if (i == first)
            {
                std::reverse(first, i_last);
                return {std::move(i_last), false};
            }
        }
    }
    template<ranges::bidirectional_range R, class Comp = ranges::less,
             class Proj = std::identity>
    requires std::sortable<ranges::iterator_t<R>, Comp, Proj>
    constexpr ranges::next_permutation_result<ranges::borrowed_iterator_t<R>>
        operator()(R&& r, Comp comp = {}, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r),
                       std::move(comp), std::move(proj));
    }
};
inline constexpr next_permutation_fn next_permutation {};

Exemple

#include <algorithm>
#include <array>
#include <compare>
#include <functional>
#include <iostream>
#include <string>
struct S
{
    char c;
    int i;
    auto operator<=>(const S&) const = default;
    friend std::ostream& operator<<(std::ostream& os, const S& s)
    {
        return os << "{'" << s.c << "', " << s.i << "}";
    }
};
auto print = [](auto const& v, char term = ' ')
{
    std::cout << "{ ";
    for (const auto& e : v)
        std::cout << e << ' ';
    std::cout << '}' << term;
};
int main()
{
    std::cout << "Générer toutes les permutations (cas des itérateurs) :\n";
    std::string s{"abc"};
    do
    {
        print(s);
    }
    while (std::ranges::next_permutation(s.begin(), s.end()).found);
    std::cout << "\n" "Générer toutes les permutations (cas des ranges) :\n";
    std::array a{'a', 'b', 'c'};
    do
    {
        print(a);
    }
    while (std::ranges::next_permutation(a).found);
    std::cout << "\n" "Générer toutes les permutations en utilisant un comparateur :\n";
    using namespace std::literals;
    std::array z{"█"s, "▄"s, "▁"s};
    do
    {
        print(z);
    }
    while (std::ranges::next_permutation(z, std::greater()).found);
    std::cout << "\n" "Générer toutes les permutations en utilisant une projection :\n";
    std::array<S, 3> r{S{'A',3}, S{'B',2}, S{'C',1}};
    do
    {
        print(r, '\n');
    }
    while (std::ranges::next_permutation(r, {}, &S::c).found);
}

Sortie :

Générer toutes les permutations (cas des itérateurs) :
{ a b c } { a c b } { b a c } { b c a } { c a b } { c b a }
Générer toutes les permutations (cas des ranges) :
{ a b c } { a c b } { b a c } { b c a } { c a b } { c b a }
Générer toutes les permutations en utilisant un comparateur :
{ █ ▄ ▁ } { █ ▁ ▄ } { ▄ █ ▁ } { ▄ ▁ █ } { ▁ █ ▄ } { ▁ ▄ █ }
Générer toutes les permutations en utilisant une projection :
{ {'A', 3} {'B', 2} {'C', 1} }
{ {'A', 3} {'C', 1} {'B', 2} }
{ {'B', 2} {'A', 3} {'C', 1} }
{ {'B', 2} {'C', 1} {'A', 3} }
{ {'C', 1} {'A', 3} {'B', 2} }
{ {'C', 1} {'B', 2} {'A', 3} }

Voir aussi

génère la permutation lexicographique précédente d'une plage d'éléments
(objet fonction algorithme)
détermine si une séquence est une permutation d'une autre séquence
(objet fonction algorithme)
génère la permutation lexicographique suivante d'une plage d'éléments
(modèle de fonction)
génère la permutation lexicographique précédente d'une plage d'éléments
(modèle de fonction)
détermine si une séquence est une permutation d'une autre séquence
(modèle de fonction)