Namespaces
Variants

std::ranges::partition

С сайта ru.cppreference.net
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы над диапазонами (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::permutable I, std::sentinel_for<I> S, class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
constexpr ranges::subrange<I>
    partition( I first, S last, Pred pred, Proj proj = {} );
(1) (начиная с C++20)
template< ranges::forward_range R, class Proj = std::identity,
          std::indirect_unary_predicate<
              std::projected<ranges::iterator_t<R>, Proj>> Pred >
requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_subrange_t<R>
    partition( R&& r, Pred pred, Proj proj = {} );
(2) (начиная с C++20)
1) Переупорядочивает элементы в диапазоне [first, last) таким образом, что проекция proj всех элементов, для которых предикат pred возвращает true, предшествует проекции proj элементов, для которых предикат pred возвращает false. Относительный порядок элементов не сохраняется.
2) То же, что и (1), но использует r в качестве исходного диапазона, как если бы ranges::begin(r) использовалось как first, а ranges::end(r) как last.

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

Параметры

first, last - пара итератор-страж, определяющая диапазон элементов для переупорядочивания
r - диапазон элементов для переупорядочивания
pred - предикат для применения к проецируемым элементам
proj - проекция для применения к элементам

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

Поддиапазон, начинающийся с итератора на первый элемент второй группы и заканчивающийся итератором, равным last . (2) возвращает std::ranges::dangling если r является rvalue не- borrowed_range типа.

Сложность

Дано N = ranges:: distance ( first, last ) , выполняется ровно N применений предиката и проекции. Не более N / 2 обменов, если I моделирует ranges::bidirectional_iterator , и не более N обменов в противном случае.

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

struct partition_fn
{
    template<std::permutable I, std::sentinel_for<I> S, class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
    constexpr ranges::subrange<I>
        operator()(I first, S last, Pred pred, Proj proj = {}) const
    {
        first = ranges::find_if_not(first, last, std::ref(pred), std::ref(proj));
        if (first == last)
            return {first, first};
        for (auto i = ranges::next(first); i != last; ++i)
        {
            if (std::invoke(pred, std::invoke(proj, *i)))
            {
                ranges::iter_swap(i, first);
                ++first;
            }
        }
        return {std::move(first), std::move(last)};
    }
    template<ranges::forward_range R, class Proj = std::identity,
             std::indirect_unary_predicate<
                 std::projected<ranges::iterator_t<R>, Proj>> Pred>
    requires std::permutable<ranges::iterator_t<R>>
    constexpr ranges::borrowed_subrange_t<R>
        operator()(R&& r, Pred pred, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), ranges::end(r),
                       std::ref(pred), std::ref(proj));
    }
};
inline constexpr partition_fn partition;

Пример

#include <algorithm>
#include <forward_list>
#include <functional>
#include <iostream>
#include <iterator>
#include <ranges>
#include <vector>
namespace ranges = std::ranges;
template<class I, std::sentinel_for<I> S, class Cmp = ranges::less>
requires std::sortable<I, Cmp>
void quicksort(I first, S last, Cmp cmp = Cmp {})
{
    using reference = std::iter_reference_t<I>;
    if (first == last)
        return;
    auto size = ranges::distance(first, last);
    auto pivot = ranges::next(first, size - 1);
    ranges::iter_swap(pivot, ranges::next(first, size / 2));
    auto tail = ranges::разделение(first, pivot, [=](reference em)
    {
        return std::invoke(cmp, em, *pivot); // em < pivot
    });
    ranges::iter_swap(pivot, tail.begin());
    quicksort(first, tail.begin(), std::ref(cmp));
    quicksort(ranges::next(tail.begin()), last, std::ref(cmp));
}
int main()
{
    std::ostream_iterator<int> cout {std::cout, " "};
    std::vector<int> v {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    std::cout << "Исходный вектор:  \t";
    ranges::copy(v, cout);
    auto tail = ranges::разделение(v, [](int i) { return i % 2 == 0; });
    std::cout << "\nРазделенный вектор: \t";
    ranges::copy(ranges::begin(v), ranges::begin(tail), cout);
    std::cout << "│ ";
    ranges::copy(tail, cout);
    std::forward_list<int> fl {1, 30, -4, 3, 5, -4, 1, 6, -8, 2, -5, 64, 1, 92};
    std::cout << "\nНеотсортированный список: \t\t";
    ranges::copy(fl, cout);
    quicksort(ranges::begin(fl), ranges::end(fl), ranges::greater {});
    std::cout << "\nБыстро отсортированный список: \t";
    ranges::copy(fl, cout);
    std::cout << '\n';
}

Возможный вывод:

Исходный вектор:        0 1 2 3 4 5 6 7 8 9
Разделенный вектор:     0 8 2 6 4 │ 5 3 7 1 9
Несортированный список: 1 30 -4 3 5 -4 1 6 -8 2 -5 64 1 92
Быстро отсортированный список: 92 64 30 6 5 3 2 1 1 1 -4 -4 -5 -8

См. также

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