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
Определено в заголовочном файле <algorithm>
Сигнатура вызова
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) (начиная с 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) (начиная с C++20)
Вспомогательный тип
template < class I >
using prev_permutation_result = ranges:: in_found_result < I > ;
(3) (начиная с C++20)
1) Преобразует диапазон [ first , last ) в предыдущую перестановку , где множество всех перестановок упорядочено лексикографически относительно бинарного функционального объекта сравнения comp и функционального объекта проекции proj .
Возвращает:
  • { last, true } если существует "предыдущая" перестановка. В противном случае,
  • { last, false } , и преобразует диапазон в (лексикографически) последнюю перестановку, как если бы с помощью
ranges::sort(first, last, comp, proj);
ranges::reverse(first, last);
2) То же, что и (1) , но использует r в качестве исходного диапазона, как если бы использовались ranges:: begin ( r ) в качестве first , и ranges:: end ( r ) в качестве last .

Функциональные сущности, описанные на этой странице, являются алгоритмическими функциональными объектами (неформально известными как niebloids ), то есть:

Содержание

Параметры

first, last - пара итератор-страж, определяющая диапазон элементов для "перестановки"
r - range элементов для "перестановки"
comp - сравнивающий FunctionObject , который возвращает true если первый аргумент меньше второго
proj - проекция, применяемая к элементам

Возвращаемое значение

1) ranges :: prev_permutation_result < I > { last, true } если новая перестановка лексикографически меньше предыдущей. ranges :: prev_permutation_result < I > { last, false } если достигнута первая перестановка и диапазон был сброшен к последней перестановке.
2) То же, что и (1) , за исключением того, что возвращаемый тип — ranges :: prev_permutation_result < ranges:: borrowed_iterator_t < R >> .

Исключения

Любые исключения, выброшенные операциями итераторов или обменом элементов.

Сложность

Не более N / 2 обменов, где N равно ranges:: distance ( first, last ) для случая (1) или ranges:: distance ( r ) для случая (2) . В среднем по всей последовательности перестановок типичные реализации используют около 3 сравнений и 1.5 обменов на вызов.

Примечания

Реализации (например, MSVC STL ) могут использовать векторизацию, когда тип итератора моделирует contiguous_iterator и обмен его типа значений не вызывает ни нетривиальные специальные функции-члены, ни ADL -найденную функцию swap .

Возможная реализация

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
    {
        // проверка, что последовательность содержит как минимум два элемента
        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;
        // основной цикл "перестановок"
        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};
            }
            // пространство "перестановок" исчерпано
            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 {};

Пример

#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 << "Генерация всех перестановок (случай с итераторами):\n";
    std::string s{"cba"};
    do print(s);
    while (std::ranges::prev_permutation(s.begin(), s.end()).found);
    std::cout << "\nГенерация всех перестановок (случай с диапазоном):\n";
    std::array a{'c', 'b', 'a'};
    do print(a);
    while (std::ranges::prev_permutation(a).found);
    std::cout << "\nГенерация всех перестановок с использованием компаратора:\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 << "\nГенерация всех перестановок с использованием проекции:\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);
}

Вывод:

Генерация всех перестановок (случай с итераторами):
{ c b a } { c a b } { b c a } { b a c } { a c b } { a b c }
Генерация всех перестановок (случай с диапазоном):
{ c b a } { c a b } { b c a } { b a c } { a c b } { a b c }
Генерация всех перестановок с использованием компаратора:
{ ▁ ▄ █ } { ▁ █ ▄ } { ▄ ▁ █ } { ▄ █ ▁ } { █ ▁ ▄ } { █ ▄ ▁ }
Генерация всех перестановок с использованием проекции:
{ {'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} }

Смотрите также

генерирует следующую большую лексикографическую перестановку диапазона элементов
(функциональный объект алгоритма)
определяет, является ли последовательность перестановкой другой последовательности
(функциональный объект алгоритма)
генерирует следующую большую лексикографическую перестановку диапазона элементов
(шаблон функции)
генерирует следующую меньшую лексикографическую перестановку диапазона элементов
(шаблон функции)
определяет, является ли последовательность перестановкой другой последовательности
(шаблон функции)