Namespaces
Variants

std::ranges:: partition

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
Definiert im Header <algorithm>
Aufrufsignatur
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) (seit 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) (seit C++20)
1) Ordnet die Elemente im Bereich [ first , last ) so um, dass die Projektion proj aller Elemente, für die das Prädikat pred true zurückgibt, vor der Projektion proj der Elemente steht, für die das Prädikat pred false zurückgibt. Die relative Reihenfolge der Elemente wird nicht beibehalten.
2) Gleich wie (1) , verwendet jedoch r als Quellbereich, als ob ranges:: begin ( r ) als first und ranges:: end ( r ) als last verwendet würde.

Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithm Function Objects (informell bekannt als Niebloids ), das heißt:

Inhaltsverzeichnis

Parameter

first, last - das Iterator-Sentinel-Paar, das den Bereich der zu reorganisierenden Elemente definiert
r - der Bereich der zu reorganisierenden Elemente
pred - Prädikat, das auf die projizierten Elemente angewendet wird
proj - Projektion, die auf die Elemente angewendet wird

Rückgabewert

Ein Teilbereich, der mit einem Iterator zum ersten Element der zweiten Gruppe beginnt und mit einem Iterator endet, der gleich last ist. (2) gibt std::ranges::dangling zurück, falls r ein R-Wert eines Nicht- borrowed_range -Typs ist.

Komplexität

Gegeben N = ranges:: distance ( first, last ) , genau N Anwendungen des Prädikats und der Projektion. Höchstens N / 2 Vertauschungen, falls I das Konzept ranges::bidirectional_iterator modelliert, andernfalls höchstens N Vertauschungen.

Mögliche Implementierung

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;

Beispiel

#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::partition(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 << "Ursprünglicher Vektor:  \t";
    ranges::copy(v, cout);
    auto tail = ranges::Partition(v, [](int i) { return i % 2 == 0; });
    std::cout << "\nPartitioned vector: \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 << "\nUnsortierte Liste: \t\t";
    ranges::copy(fl, cout);
    quicksort(ranges::begin(fl), ranges::end(fl), ranges::greater {});
    std::cout << "\nQuick-sortierte Liste: \t";
    ranges::copy(fl, cout);
    std::cout << '\n';
}

Mögliche Ausgabe:

Ursprünglicher Vektor:  0 1 2 3 4 5 6 7 8 9
Partitionierter Vektor: 0 8 2 6 4 │ 5 3 7 1 9
Unsortierte Liste:      1 30 -4 3 5 -4 1 6 -8 2 -5 64 1 92
Quick-sortierte Liste:  92 64 30 6 5 3 2 1 1 1 -4 -4 -5 -8

Siehe auch

kopiert einen Bereich und unterteilt die Elemente in zwei Gruppen
(Algorithmus-Funktionsobjekt)
bestimmt, ob der Bereich durch das gegebene Prädikat partitioniert ist
(Algorithmus-Funktionsobjekt)
unterteilt Elemente in zwei Gruppen unter Beibehaltung ihrer relativen Reihenfolge
(Algorithmus-Funktionsobjekt)
unterteilt einen Elementbereich in zwei Gruppen
(Funktions-Template)