Namespaces
Variants

std::ranges::stable_partition

Depuis fr.cppreference.net
 
 
Bibliothèque d'algorithmes
Algorithmes contraints et algorithmes sur plages (C++20)
Algorithmes contraints, p. ex. ranges::copy, ranges::sort, ...
Opérations de séquence non modificatrices    
Opérations par lots
(C++17)
Opérations de recherche
Opérations de séquence modificatrices
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)

Opérations de tri et connexes
Opérations de partitionnement
(C++11)    

Opérations de tri
Opérations de recherche binaire
(sur des plages partitionnées)
Opérations d'ensemble (sur des plages triées)
Opérations de fusion (sur des plages triées)
Opérations de tas
Opérations 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 modificatrices
Opérations de séquence modificatrices
Opérations de partitionnement
Opérations de tri
Opérations de recherche binaire (sur des plages triées)
       
       
Opérations d'ensemble (sur des plages triées)
Opérations de tas
Opérations 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::bidirectional_iterator I, std::sentinel_for<I> S,
          class Proj = std::identity,
          std::indirect_unary_predicate<std::projected<I, Proj>> Pred >
requires std::permutable<I>
ranges::subrange<I>
    stable_partition( I first, S last, Pred pred, Proj proj = {} );
(1) (depuis C++20)
(constexpr depuis C++26)
template< ranges::bidirectional_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>>
ranges::borrowed_subrange_t<R>
    stable_partition( R&& r, Pred pred, Proj proj = {} );
(2) (depuis C++20)
(constexpr depuis C++26)
1) Réorganise les éléments dans la plage [firstlast) de telle manière que la projection proj de tous les éléments pour lesquels le prédicat pred retourne true précèdent la projection proj des éléments pour lesquels le prédicat pred retourne false. L'algorithme est stable, c'est-à-dire que l'ordre relatif des éléments est préservé.
2) Identique à (1), mais utilise r comme plage, comme si en utilisant ranges::begin(r) comme first et ranges::end(r) comme last.

Les entités apparentées à des fonctions décrites sur cette page sont des objets fonctions algorithmiques (informellement appelés niebloids), c'est-à-dire :

Paramètres

first, last - la paire itérateur-sentinelle définissant l'intervalle des éléments à réorganiser
r - l'intervalle des éléments à réorganiser
pred - prédicat à appliquer aux éléments projetés
proj - projection à appliquer aux éléments

Valeur de retour

1) Un objet égal à { pivot, last } , où pivot est un itérateur vers le premier élément du second groupe.
2) Identique à (1) si r est une lvalue ou d'un type borrowed_range . Sinon, retourne std::ranges::dangling .

Complexité

Étant donné N = ranges:: distance ( first, last ) , la complexité est au pire N·log(N) échanges, et seulement 𝓞(N) échanges dans le cas où un tampon mémoire supplémentaire est utilisé. Exactement N applications du prédicat pred et de la projection proj .

Notes

Cette fonction tente d'allouer un tampon temporaire. Si l'allocation échoue, l'algorithme moins efficace est choisi.

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_lib_constexpr_algorithms 202306L (C++26) constexpr tri stable

Implémentation possible

Cette implémentation n'utilise pas de tampon mémoire supplémentaire et peut donc être moins efficace. Voir également l'implémentation dans MSVC STL et libstdc++ .

struct stable_partition_fn
{
    template<std::bidirectional_iterator I, std::sentinel_for<I> S,
             class Proj = std::identity,
             std::indirect_unary_predicate<std::projected<I, Proj>> Pred>
    requires std::permutable<I>
    constexpr ranges::subrange<I>
        operator()(I first, S last, Pred pred, Proj proj = {}) const
    {
        first = ranges::find_if_not(first, last, pred, proj);
        I mid = first;
        while (mid != last)
        {
            mid = ranges::find_if(mid, last, pred, proj);
            if (mid == last)
                break;
            I last2 = ranges::find_if_not(mid, last, pred, proj);
            ranges::rotate(first, mid, last2);
            first = ranges::next(first, ranges::distance(mid, last2));
            mid = last2;
        }
        return {std::move(first), std::move(mid)};
    }
    template<ranges::bidirectional_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::move(pred), std::move(proj));
    }
};
inline constexpr stable_partition_fn stable_partition {};

Exemple

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
namespace rng = std::ranges;
template<std::permutable I, std::sentinel_for<I> S>
constexpr void stable_sort(I first, S last)
{
    if (first == last)
        return;
    auto pivot = *rng::next(first, rng::distance(first, last) / 2, last);
    auto left = [pivot](const auto& em) { return em < pivot; };
    auto tail1 = rng::stable_partition(first, last, left);
    auto right = [pivot](const auto& em) { return !(pivot < em); };
    auto tail2 = rng::stable_partition(tail1, right);
    stable_sort(first, tail1.begin());
    stable_sort(tail2.begin(), tail2.end());
}
void print(const auto rem, auto first, auto last, bool end = true)
{
    std::cout << rem;
    for (; first != last; ++first)
        std::cout << *first << ' ';
    std::cout << (end ? "\n" : "");
}
int main()
{
    const auto original = {9, 6, 5, 2, 3, 1, 7, 8};
    std::vector<int> vi {};
    auto even = [](int x) { return 0 == (x % 2); };
    print("Original vector:\t", original.begin(), original.end(), "\n");
    vi = original;
    const auto ret1 = rng::stable_partition(vi, even);
    print("Stable partitioned:\t", vi.begin(), ret1.begin(), 0);
    print("│ ", ret1.begin(), ret1.end());
    vi = original;
    const auto ret2 = rng::partition(vi, even);
    print("Partitioned:\t\t", vi.begin(), ret2.begin(), 0);
    print("│ ", ret2.begin(), ret2.end());
    vi = {16, 30, 44, 30, 15, 24, 10, 18, 12, 35};
    print("Unsorted vector: ", vi.begin(), vi.end());
    stable_sort(rng::begin(vi), rng::end(vi));
    print("Sorted vector:   ", vi.begin(), vi.end());
}

Sortie possible :

Original vector:        9 6 5 2 3 1 7 8
Stable partitioned:     6 2 8 │ 9 5 3 1 7
Partitioned:            8 6 2 │ 5 3 1 7 9
Unsorted vector: 16 30 44 30 15 24 10 18 12 35
Sorted vector:   10 12 15 16 18 24 30 30 35 44

Voir aussi

divise une plage d'éléments en deux groupes
(objet de fonction d'algorithme)
copie une plage en divisant les éléments en deux groupes
(objet de fonction d'algorithme)
détermine si la plage est partitionnée par le prédicat donné
(objet de fonction d'algorithme)
divise les éléments en deux groupes tout en préservant leur ordre relatif dans chaque groupe
(modèle de fonction)