Namespaces
Variants

std::ranges::partition

Depuis fr.cppreference.net
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur plages (C++20)
Algorithmes contraints, par ex. ranges::copy, ranges::sort, ...
Opérations de séquence non modifiantes    
Opérations par lots
(C++17)
Opérations de recherche
Opérations de séquence modifiantes
Opérations de copie
(C++11)
(C++11)
Opérations d'échange
Opérations de transformation
Opérations de génération
Opérations de suppression
Opérations de changement d'ordre
(jusqu'à C++17)(C++11)
(C++20)(C++20)
Opérations d'échantillonnage
(C++17)

Tri et opérations associées
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur plages partitionnées)
Opérations d'ensemble (sur plages triées)
Opérations de fusion (sur plages triées)
Opérations de tas
Opérations de minimum/maximum
(C++11)
(C++17)
Opérations de comparaison lexicographique
Opérations de permutation


 
Algorithmes contraints
Tous les noms de ce menu appartiennent à l'espace de noms std::ranges
Opérations de séquence non modifiantes
Opérations de séquence modifiantes
Opérations de partitionnement
Opérations de tri
Opérations de recherche binaire (sur plages triées)
       
       
Opérations d'ensemble (sur plages triées)
Opérations de tas
Opérations de minimum/maximum
       
       
Opérations de permutation
Opérations de pliage
Opérations sur le stockage non initialisé
Types de retour
 
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)
1) Réordonne les éléments dans la plage [firstlast) 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é.
2) Identique à (1), mais utilise 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 :

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

copie une plage en divisant les éléments en deux groupes
(objet fonction d'algorithme)
détermine si la plage est partitionnée par le prédicat donné
(objet fonction d'algorithme)
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)