std::ranges::partition
| Défini dans l'en-tête <algorithm>
|
||
| Signature d'appel |
||
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) | (depuis 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) | (depuis C++20) |
[first, last) de telle sorte que la projection proj de tous les éléments pour lesquels le prédicat pred retourne true précède la projection proj des éléments pour lesquels le prédicat pred retourne false. L'ordre relatif des éléments n'est pas préservé.r comme plage source, comme si en utilisant ranges::begin(r) comme first et ranges::end(r) comme last.Les entités de type fonction décrites sur cette page sont des objets de fonction d'algorithme (informellement appelés niebloids), c'est-à-dire :
- Les listes d'arguments de modèle explicites ne peuvent pas être spécifiées lors de l'appel de l'un d'entre eux.
- Aucun d'entre eux n'est visible par recherche dépendante des arguments.
- Lorsque l'un d'entre eux est trouvé par recherche non qualifiée normale comme nom à gauche de l'opérateur d'appel de fonction, la recherche dépendante des arguments est inhibée.
Paramètres
| first, last | - | la paire itérateur-sentinelle définissant la plage des éléments à réorganiser |
| r | - | la plage d'éléments à réorganiser |
| pred | - | prédicat à appliquer aux éléments projetés |
| proj | - | projection à appliquer aux éléments |
Valeur de retour
Un sous-intervalle commençant par un itérateur vers le premier élément du deuxième groupe et se terminant par un itérateur égal à
last
.
(2)
renvoie
std::ranges::dangling
si
r
est une rvalue d'un type non-
borrowed_range
.
Complexité
Étant donné
N
=
ranges::
distance
(
first, last
)
, exactement
N
applications du prédicat et de la projection. Au maximum
N / 2
échanges si
I
modélise
ranges::bidirectional_iterator
, et au maximum
N
échanges sinon.
Implémentation possible
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; |
Exemple
#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 << "Vecteur original : \t"; ranges::copy(v, cout); auto tail = ranges::partition(v, [](int i) { return i % 2 == 0; }); std::cout << "\nVecteur partitionné : \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 << "\nListe non triée : \t\t"; ranges::copy(fl, cout); quicksort(ranges::begin(fl), ranges::end(fl), ranges::greater {}); std::cout << "\nListe triée par tri rapide : \t"; ranges::copy(fl, cout); std::cout << '\n'; }
Sortie possible :
Vecteur original : 0 1 2 3 4 5 6 7 8 9 Vecteur partitionné : 0 8 2 6 4 │ 5 3 7 1 9 Liste non triée : 1 30 -4 3 5 -4 1 6 -8 2 -5 64 1 92 Liste triée par quicksort : 92 64 30 6 5 3 2 1 1 1 -4 -4 -5 -8
Voir aussi
(C++20) |
copie une plage en divisant les éléments en deux groupes (objet fonction d'algorithme) |
(C++20) |
détermine si la plage est partitionnée par le prédicat donné (objet fonction d'algorithme) |
(C++20) |
divise les éléments en deux groupes tout en préservant leur ordre relatif au sein de chaque groupe (objet fonction d'algorithme) |
| divise une plage d'éléments en deux groupes (modèle de fonction) |