Namespaces
Variants

std::ranges::is_permutation

С std::ranges::is_permutation
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы над диапазонами (C++20)
Ограниченные алгоритмы, например ranges::copy, ranges::sort, ...
Операции последовательностей без изменения    
Пакетные операции
(C++17)
Операции поиска
Операции изменения последовательностей
Операции копирования
(C++11)
(C++11)
Операции обмена
Операции преобразования
Операции генерации
Операции удаления
Операции изменения порядка
(до C++17)(C++11)
(C++20)(C++20)
Операции выборки
(C++17)

Сортировка и связанные операции
Операции разбиения
(C++11)    

Операции сортировки
Операции бинарного поиска
(на разбитых диапазонах)
Операции над множествами (на отсортированных диапазонах)
Операции слияния (на отсортированных диапазонах)
Операции с кучей
Операции минимума/максимума
(C++11)
(C++17)
Операции лексикографического сравнения
Операции перестановок


Политики выполнения (C++17)
(только для демонстрации*)(C++26)

Численные операции
(C++11)
(C++17)
(C++17)    

Специализированные <memory> алгоритмы

Специализированные <random> алгоритмы
Библиотека C









 
Ограниченные алгоритмы
Все имена в этом меню принадлежат пространству имен std::ranges
Операции последовательностей без изменения
Операции изменения последовательностей
Операции разбиения
Операции сортировки
Операции бинарного поиска (на отсортированных диапазонах)
       
       
Операции над множествами (на отсортированных диапазонах)
Операции с кучей
Операции минимума/максимума
       
       
Операции перестановок
Операции свертки
Операции над неинициализированной памятью
Типы возврата
 
Определено в заголовке <algorithm>
Сигнатура вызова
template< std::forward_iterator I1, std::sentinel_for<I1> S1,
          std::forward_iterator I2, std::sentinel_for<I2> S2,
          class Proj1 = std::identity, class Proj2 = std::identity,
          std::indirect_equivalence_relation<std::projected<I1, Proj1>,
                                             std::projected<I2, Proj2>>
                                                 Pred = ranges::equal_to >
constexpr bool
    is_permutation( I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {},
                    Proj1 proj1 = {}, Proj2 proj2 = {} );
(1) (начиная с C++20)
template< ranges::forward_range R1, ranges::forward_range R2,
          class Proj1 = std::identity, class Proj2 = std::identity,
          std::indirect_equivalence_relation<
              std::projected<ranges::iterator_t<R1>, Proj1>,
              std::projected<ranges::iterator_t<R2>, Proj2>>
                  Pred = ranges::equal_to >
constexpr bool
    is_permutation( R1&& r1, R2&& r2, Pred pred = {},
                    Proj1 proj1 = {}, Proj2 proj2 = {} );
(2) (начиная с C++20)
1) Возвращает true если существует перестановка элементов в диапазоне [first1, last1), которая делает диапазон равным диапазону [first2, last2) (после применения соответствующих проекций Proj1, Proj2 и использования бинарного предиката Pred в качестве компаратора). В противном случае возвращает false.
2) То же, что (1), но использует r1 в качестве первого исходного диапазона и r2 в качестве второго исходного диапазона, как если бы использовались ranges::begin(r1) как first1, ranges::end(r1) как last1, ranges::begin(r2) как first2 и ranges::end(r2) как last2.

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

Параметры

first1, last1 - пара итератор-страж, определяющая первый диапазон элементов
first2, last2 - пара итератор-страж, определяющая второй диапазон элементов
r1 - первый range элементов
r2 - второй range элементов
pred - предикат для применения к проецируемым элементам
proj1 - проекция для применения к элементам первого диапазона
proj2 - проекция для применения к элементам второго диапазона

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

true если диапазон [ first1 , last1 ) является перестановкой диапазона [ first2 , last2 ) .

Сложность

Не более O(N 2 ) применений предиката и каждой проекции, или ровно N если последовательности уже равны, где N равно ranges:: distance ( first1, last1 ) . Однако если ranges:: distance ( first1, last1 ) ! = ranges:: distance ( first2, last2 ) , применения предиката и проекций не производятся.

Примечания

Отношение перестановки является отношением эквивалентности .

Функция ranges::is_permutation может использоваться в тестировании, например, для проверки корректности алгоритмов перестановки, таких как сортировка, перемешивание, разделение. Если p является исходной последовательностью, а q - "изменённой" последовательностью, то ranges :: is_permutation ( p, q ) == true означает, что q состоит из "тех же" элементов (возможно, переставленных), что и p .

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

struct is_permutation_fn
{
    template<std::forward_iterator I1, std::sentinel_for<I1> S1,
             std::forward_iterator I2, std::sentinel_for<I2> S2,
             class Proj1 = std::identity, class Proj2 = std::identity,
             std::indirect_equivalence_relation<std::projected<I1, Proj1>,
                                                std::projected<I2, Proj2>>
                                                    Pred = ranges::equal_to>
    constexpr bool operator()(I1 first1, S1 last1, I2 first2, S2 last2,
                              Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}) const
    {
        // пропустить общий префикс
        auto ret = std::ranges::mismatch(first1, last1, first2, last2,
                                         std::ref(pred), std::ref(proj1), std::ref(proj2));
        first1 = ret.in1, first2 = ret.in2;
        // перебираем остальные, подсчитывая, сколько раз встречается каждый элемент
        // из [first1, last1) появляется в [first2, last2)
        for (auto i {first1}; i != last1; ++i)
        {
            const auto i_proj {std::invoke(proj1, *i)};
            auto i_cmp = [&]<typename T>(T&& t)
            { 
                return std::invoke(pred, i_proj, std::forward<T>(t));
            };
            if (i != ranges::find_if(first1, i, i_cmp, proj1))
                continue; // этот *i был проверен
            if (const auto m {ranges::count_if(first2, last2, i_cmp, proj2)};
                m == 0 or m != ranges::count_if(i, last1, i_cmp, proj1))
                return false;
        }
        return true;
    }
    template<ranges::forward_range R1, ranges::forward_range R2,
             class Proj1 = std::identity, class Proj2 = std::identity,
             std::indirect_equivalence_relation<
                 std::projected<ranges::iterator_t<R1>, Proj1>,
                 std::projected<ranges::iterator_t<R2>, Proj2>>
                     Pred = ranges::equal_to>
    constexpr bool operator()(R1&& r1, R2&& r2, Pred pred = {},
                              Proj1 proj1 = {}, Proj2 proj2 = {}) const
    {
        return (*this)(ranges::begin(r1), ranges::end(r1),
                       ranges::begin(r2), ranges::end(r2),
                       std::move(pred), std::move(proj1), std::move(proj2));
    }
};
inline constexpr is_permutation_fn is_permutation {};

Пример

#include <algorithm>
#include <array>
#include <cmath>
#include <iostream>
#include <ranges>
auto& operator<<(auto& os, std::ranges::forward_range auto const& v)
{
    os << "{ ";
    for (const auto& e : v)
        os << e << ' ';
    return os << "}";
}
int main()
{
    static constexpr auto r1 = {1, 2, 3, 4, 5};
    static constexpr auto r2 = {3, 5, 4, 1, 2};
    static constexpr auto r3 = {3, 5, 4, 1, 1};
    static_assert(
        std::ranges::is_permutation(r1, r1) &&
        std::ranges::is_permutation(r1, r2) &&
        std::ranges::is_permutation(r2, r1) &&
        std::ranges::is_permutation(r1.begin(), r1.end(), r2.begin(), r2.end()));
    std::cout
        << std::boolalpha
        << "is_permutation(" << r1 << ", " << r2 << "): "
        << std::ranges::is_permutation(r1, r2) << '\n'
        << "is_permutation(" << r1 << ", " << r3 << "): "
        << std::ranges::is_permutation(r1, r3) << '\n'
        << "is_permutation with custom predicate and projections: "
        << std::ranges::is_permutation(
            std::array {-14, -11, -13, -15, -12},  // 1st range
            std::array {'F', 'E', 'C', 'B', 'D'},  // 2nd range
            [](int x, int y) { return abs(x) == abs(y); }, // predicate
            [](int x) { return x + 10; },          // projection for 1st range
            [](char y) { return int(y - 'A'); })   // projection for 2nd range
        << '\n';
}

Вывод:

is_permutation({ 1 2 3 4 5 }, { 3 5 4 1 2 }): true
is_permutation({ 1 2 3 4 5 }, { 3 5 4 1 1 }): false
is_permutation with custom predicate and projections: true

Смотри также

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