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
Definido en el encabezado <algorithm>
Firma de llamada
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) (desde 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) (desde C++20)
Tipo auxiliar
template < class I >
using prev_permutation_result = ranges:: in_found_result < I > ;
(3) (desde C++20)
1) Transforma el rango [ first , last ) en la permutación anterior, donde el conjunto de todas las permutaciones está ordenado lexicográficamente con respecto al objeto función de comparación binaria comp y el objeto función de proyección proj .
Devuelve:
  • { last, true } si existe la permutación "anterior". De lo contrario,
  • { last, false } , y transforma el rango en la última permutación (lexicográficamente), como si se hiciera mediante
ranges::sort(first, last, comp, proj);
ranges::reverse(first, last);
2) Igual que (1) , pero utiliza r como el rango fuente, como si se usara ranges:: begin ( r ) como first , y ranges:: end ( r ) como last .

Las entidades similares a funciones descritas en esta página son algorithm function objects (conocidas informalmente como niebloids ), es decir:

Contenidos

Parámetros

first, last - el par iterador-centinela que define el rango de elementos a "permutar"
r - el range de elementos a "permutar"
comp - objeto función de comparación FunctionObject que devuelve true si el primer argumento es menor que el segundo
proj - proyección a aplicar a los elementos

Valor de retorno

1) ranges :: prev_permutation_result < I > { last, true } si la nueva permutación es lexicográficamente menor que la anterior. ranges :: prev_permutation_result < I > { last, false } si se alcanzó la primera permutación y el rango se restableció a la última permutación.
2) Igual que (1) excepto que el tipo de retorno es ranges :: prev_permutation_result < ranges:: borrowed_iterator_t < R >> .

Excepciones

Cualquier excepción lanzada desde operaciones de iteradores o el intercambio de elementos.

Complejidad

A lo sumo N / 2 intercambios, donde N es ranges:: distance ( first, last ) en el caso (1) o ranges:: distance ( r ) en el caso (2) . Promediado sobre toda la secuencia de permutaciones, las implementaciones típicas usan aproximadamente 3 comparaciones y 1.5 intercambios por llamada.

Notas

Las implementaciones (por ejemplo, MSVC STL ) pueden habilitar la vectorización cuando el tipo de iterador modela contiguous_iterator y el intercambio de su tipo de valor no llama ni a funciones miembro especiales no triviales ni a ADL -encontrado swap .

Implementación posible

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
    {
        // verificar que la secuencia tiene al menos dos elementos
        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;
        // bucle principal de "permutación"
        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};
            }
            // se agota el "espacio" de permutación
            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 {};

Ejemplo

#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 << "Generate all permutations (iterators case):\n";
    std::string s{"cba"};
    do print(s);
    while (std::ranges::prev_permutation(s.begin(), s.end()).found);
    std::cout << "\nGenerate all permutations (range case):\n";
    std::array a{'c', 'b', 'a'};
    do print(a);
    while (std::ranges::prev_permutation(a).found);
    std::cout << "\nGenerate all permutations using comparator:\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 << "\nGenerate all permutations using 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);
}

Salida:

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} }

Véase también

genera la siguiente permutación lexicográfica mayor de un rango de elementos
(objeto función de algoritmo)
determina si una secuencia es una permutación de otra secuencia
(objeto función de algoritmo)
genera la siguiente permutación lexicográfica mayor de un rango de elementos
(plantilla de función)
genera la siguiente permutación lexicográfica menor de un rango de elementos
(plantilla de función)
determina si una secuencia es una permutación de otra secuencia
(plantilla de función)