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
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 next_permutation_result < I >

next_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 next_permutation_result < ranges:: borrowed_iterator_t < R >>

next_permutation ( R && r, Comp comp = { } , Proj proj = { } ) ;
(2) (desde C++20)
Tipo auxiliar
template < class I >
using next_permutation_result = ranges:: in_found_result < I > ;
(3) (desde C++20)
1) Transforma el rango [ first , last ) en la siguiente permutación , donde el conjunto de todas las permutaciones está ordenado lexicográficamente con respecto al objeto función de comparación binaria comp y al objeto función de proyección proj . Devuelve { last, true } si existe tal "siguiente permutación" ; de lo contrario, transforma el rango en la primera permutación lexicográfica como si mediante ranges:: sort ( first, last, comp, proj ) , y devuelve { last, false } .
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 de 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 :: next_permutation_result < I > { last, true } si la nueva permutación es lexicográficamente mayor que la anterior. ranges :: next_permutation_result < I > { last, false } si se alcanzó la última permutación y el rango se restableció a la primera permutación.
2) Igual que (1) excepto que el tipo de retorno es ranges :: next_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 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
    {
        // verificar que la secuencia tiene al menos dos elementos
        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};
        // bucle principal de "permutación"
        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};
            }
            // se agota el "espacio" de permutación
            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 {};

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 << "Generar todas las permutaciones (caso de iteradores):\n";
    std::string s{"abc"};
    do
    {
        print(s);
    }
    while (std::ranges::next_permutation(s.begin(), s.end()).found);
    std::cout << "\n" "Generar todas las permutaciones (caso de rango):\n";
    std::array a{'a', 'b', 'c'};
    do
    {
        print(a);
    }
    while (std::ranges::next_permutation(a).found);
    std::cout << "\n" "Generar todas las permutaciones usando comparador:\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" "Generar todas las permutaciones usando proyección:\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);
}

Salida:

Generar todas las permutaciones (caso de iteradores):
{ a b c } { a c b } { b a c } { b c a } { c a b } { c b a }
Generar todas las permutaciones (caso de rango):
{ a b c } { a c b } { b a c } { b c a } { c a b } { c b a }
Generar todas las permutaciones usando comparador:
{ █ ▄ ▁ } { █ ▁ ▄ } { ▄ █ ▁ } { ▄ ▁ █ } { ▁ █ ▄ } { ▁ ▄ █ }
Generar todas las permutaciones usando proyección:
{ {'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} }

Véase también

genera la siguiente permutación lexicográfica más pequeña 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 más pequeña de un rango de elementos
(plantilla de función)
determina si una secuencia es una permutación de otra secuencia
(plantilla de función)