Namespaces
Variants

std::ranges:: prev_permutation, std::ranges:: prev_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 prev_permutation_result < I >

prev_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 prev_permutation_result < ranges:: borrowed_iterator_t < R >>

prev_permutation ( R && r, Comp comp = { } , Proj proj = { } ) ;
(2) (depuis C++20)
Type auxiliaire
template < class I >
using prev_permutation_result = ranges:: in_found_result < I > ;
(3) (depuis C++20)
1) Transforme la plage [ first , last ) en la permutation précédente, 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 permutation "précédente" existe. Sinon,
  • { last, false } , et transforme la plage en la dernière permutation (lexicographiquement), comme si par
ranges::sort(first, last, comp, proj);
ranges::reverse(first, last);
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 :: prev_permutation_result < I > { last, true } si la nouvelle permutation est lexicographiquement inférieure à l'ancienne. ranges :: prev_permutation_result < I > { last, false } si la première permutation a été atteinte et que la plage a été réinitialisée à la dernière permutation.
2) Identique à (1) sauf que le type de retour est ranges :: prev_permutation_result < ranges:: borrowed_iterator_t < R >> .

Exceptions

Toute exception levée par les opérations sur les itérateurs 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 prev_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::prev_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};
        auto i{first};
        ++i;
        if (i == last)
            return {std::move(i), false};
        auto i_last{ranges::next(first, last)};
        i = i_last;
        --i;
        // boucle principale de "permutation"
        for (;;)
        {
            auto i1{i};
            --i;
            if (std::invoke(comp, std::invoke(proj, *i1), std::invoke(proj, *i)))
            {
                auto j{i_last};
                while (!std::invoke(comp, std::invoke(proj, *--j), std::invoke(proj, *i)))
                    ;
                ranges::iter_swap(i, j);
                ranges::reverse(i1, last);
                return {std::move(i_last), true};
            }
            // l'espace de "permutation" est épuisé
            if (i == first)
            {
                ranges::reverse(first, 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::prev_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 prev_permutation_fn prev_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{"cba"};
    do print(s);
    while (std::ranges::prev_permutation(s.begin(), s.end()).found);
    std::cout << "\nGénérer toutes les permutations (cas des plages) :\n";
    std::array a{'c', 'b', 'a'};
    do print(a);
    while (std::ranges::prev_permutation(a).found);
    std::cout << "\nGé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::prev_permutation(z, std::greater()).found);
    std::cout << "\nGénérer toutes les permutations en utilisant une projection :\n";
    std::array<S, 3> r{S{'C',1}, S{'B',2}, S{'A',3}};
    do print(r, '\n');
    while (std::ranges::prev_permutation(r, {}, &S::c).found);
}

Sortie :

Generate all permutations (iterators case):
{ c b a } { c a b } { b c a } { b a c } { a c b } { a b c }
Generate all permutations (range case):
{ c b a } { c a b } { b c a } { b a c } { a c b } { a b c }
Generate all permutations using comparator:
{ ▁ ▄ █ } { ▁ █ ▄ } { ▄ ▁ █ } { ▄ █ ▁ } { █ ▁ ▄ } { █ ▄ ▁ }
Generate all permutations using projection:
{ {'C', 1} {'B', 2} {'A', 3} }
{ {'C', 1} {'A', 3} {'B', 2} }
{ {'B', 2} {'C', 1} {'A', 3} }
{ {'B', 2} {'A', 3} {'C', 1} }
{ {'A', 3} {'C', 1} {'B', 2} }
{ {'A', 3} {'B', 2} {'C', 1} }

Voir aussi

génère la prochaine permutation lexicographique supérieure d'une plage d'éléments
(objet fonction d'algorithme)
détermine si une séquence est une permutation d'une autre séquence
(objet fonction d'algorithme)
génère la prochaine permutation lexicographique supérieure d'une plage d'éléments
(modèle de fonction)
génère la prochaine permutation lexicographique inférieure 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)