Namespaces
Variants

std::ranges:: inplace_merge

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:: bidirectional_iterator I, std:: sentinel_for < I > S,

class Comp = ranges:: less , class Proj = std:: identity >
requires std:: sortable < I, Comp, Proj >
I inplace_merge ( I first, I middle, S last,

Comp comp = { } , Proj proj = { } ) ;
(1) (seit C++20)
(constexpr seit C++26)
template < ranges:: bidirectional_range R, class Comp = ranges:: less ,

class Proj = std:: identity >
requires std:: sortable < ranges:: iterator_t < R > , Comp, Proj >
ranges:: borrowed_iterator_t < R >
inplace_merge ( R && r, ranges:: iterator_t < R > middle,

Comp comp = { } , Proj proj = { } ) ;
(2) (seit C++20)
(constexpr seit C++26)

Führt zwei aufeinanderfolgende sortierte Bereiche [ first , middle ) und [ middle , last ) zu einem sortierten Bereich [ first , last ) zusammen.

Eine Sequenz wird als sortiert bezüglich des Komparators comp und der Projektion proj bezeichnet, wenn für jeden Iterator it , der auf die Sequenz zeigt, und jede nicht-negative Ganzzahl n , sodass it + n ein gültiger Iterator ist, der auf ein Element der Sequenz zeigt, std:: invoke ( comp, std:: invoke ( proj, * ( it + n ) ) , std:: invoke ( proj, * it ) ) ) zu false ausgewertet wird.

Diese Merge-Funktion ist stabil , was bedeutet, dass für äquivalente Elemente in den beiden ursprünglichen Bereichen die Elemente aus dem ersten Bereich (unter Beibehaltung ihrer ursprünglichen Reihenfolge) vor den Elementen aus dem zweiten Bereich (unter Beibehaltung ihrer ursprünglichen Reihenfolge) stehen.

1) Elemente werden mit der gegebenen binären Vergleichsfunktion comp und dem Projektionsobjekt proj verglichen, und die Bereiche müssen entsprechend sortiert sein.
2) Gleich wie (1) , verwendet jedoch r als Bereich, 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 - der Anfang des ersten sortierten Bereichs
middle - das Ende des ersten Bereichs und der Anfang des zweiten Bereichs
last - das Ende des zweiten sortierten Bereichs
r - der Bereich der Elemente, die in-place zusammengeführt werden sollen
comp - Vergleich, der auf die projizierten Elemente angewendet wird
proj - Projektion, die auf die Elemente im Bereich angewendet wird

Rückgabewert

Ein Iterator gleich last .

Komplexität

Genau N − 1 Vergleiche, wenn ein zusätzlicher Speicherpuffer verfügbar ist, wobei N = ranges:: distance ( first, last ) . Andernfalls 𝓞(N•log(N)) Vergleiche. Zusätzlich in beiden Fällen doppelt so viele Projektionen wie Vergleiche.

Hinweise

Diese Funktion versucht, einen temporären Puffer zu allozieren. Wenn die Allokation fehlschlägt, wird der weniger effiziente Algorithmus gewählt.

Feature-Test Makro Wert Std Funktion
__cpp_lib_constexpr_algorithms 202306L (C++26) constexpr stabile Sortierung

Mögliche Implementierung

Diese Implementierung zeigt nur den langsameren Algorithmus, der verwendet wird, wenn kein zusätzlicher Speicher verfügbar ist. Siehe auch die Implementierung in MSVC STL und libstdc++ .

struct inplace_merge_fn
{
    template<std::bidirectional_iterator I, std::sentinel_for<I> S,
             class Comp = ranges::less, class Proj = std::identity>
    requires std::sortable<I, Comp, Proj>
    constexpr I operator()(I first, I middle, S last, Comp comp = {}, Proj proj = {}) const
    {
        I last_it = ranges::next(middle, last);
        inplace_merge_slow(first, middle, last_it,
                           ranges::distance(first, middle),
                           ranges::distance(middle, last_it),
                           std::ref(comp), std::ref(proj));
        return last_it;
    }
    template<ranges::bidirectional_range R, class Comp = ranges::less,
             class Proj = std::identity>
    requires std::sortable<ranges::iterator_t<R>, Comp, Proj>
    constexpr ranges::borrowed_iterator_t<R>
        operator()(R&& r, ranges::iterator_t<R> middle,
                   Comp comp = {}, Proj proj = {}) const
    {
        return (*this)(ranges::begin(r), std::move(middle), ranges::end(r),
                       std::move(comp), std::move(proj));
    }
private:
    template<class I, class Comp, class Proj>
    static constexpr void inplace_merge_slow(I first, I middle, I last,
                                             std::iter_difference_t<I> n1,
                                             std::iter_difference_t<I> n2,
                                             Comp comp, Proj proj)
    {
        if (n1 == 0 || n2 == 0)
            return;
        if (n1 + n2 == 2 && comp(proj(*middle), proj(*first)))
        {
            ranges::iter_swap(first, middle);
            return;
        }
        I cut1 = first, cut2 = middle;
        std::iter_difference_t<I> d1{}, d2{};
        if (n1 > n2)
        {
            d1 = n1 / 2;
            ranges::advance(cut1, d1);
            cut2 = ranges::lower_bound(middle, last, *cut1,
                                       std::ref(comp), std::ref(proj));
            d2 = ranges::distance(middle, cut2);
        }
        else
        {
            d2 = n2 / 2;
            ranges::advance(cut2, d2);
            cut1 = ranges::upper_bound(first, middle, *cut2,
                                       std::ref(comp), std::ref(proj));
            d1 = ranges::distance(first, cut1);
        }
        I new_middle = ranges::rotate(cut1, middle, cut2);
        inplace_merge_slow(first, cut1, new_middle, d1, d2,
                           std::ref(comp), std::ref(proj));
        inplace_merge_slow(new_middle, cut2, last, n1 - d1, n2 - d2,
                           std::ref(comp), std::ref(proj));
    }
};
inline constexpr inplace_merge_fn inplace_merge {};

Beispiel

#include <algorithm>
#include <complex>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
void print(auto const& v, auto const& rem, int middle = -1)
{
    for (int i{}; auto n : v)
        std::cout << (i++ == middle ? "│ " : "") << n << ' ';
    std::cout << rem << '\n';
}
template<std::random_access_iterator I, std::sentinel_for<I> S>
requires std::sortable<I>
void merge_sort(I first, S last)
{
    if (last - first > 1)
    {
        I middle{first + (last - first) / 2};
        merge_sort(first, middle);
        merge_sort(middle, last);
        std::ranges::inplace_merge(first, middle, last);
    }
}
int main()
{
    // benutzerdefinierte Merge-Sort-Demo
    std::vector v{8, 2, 0, 4, 9, 8, 1, 7, 3};
    print(v, ": vor der Sortierung");
    merge_sort(v.begin(), v.end());
    print(v, ": nach der Sortierung\n");
    // Zusammenführen mit Vergleichsfunktionsobjekt und Projektion
    using CI = std::complex<int>;
    std::vector<CI> r{{0,1}, {0,2}, {0,3}, {1,1}, {1,2}};
    const auto middle{std::ranges::next(r.begin(), 3)};
    auto comp{std::ranges::less{}};
    auto proj{[](CI z) { return z.imag(); }};
    print(r, ": vor dem Zusammenführen", middle - r.begin());
    std::ranges::inplace_merge(r, middle, comp, proj);
    print(r, ": nach dem Zusammenführen");
}

Ausgabe:

8 2 0 4 9 8 1 7 3 : vor der Sortierung
0 1 2 3 4 7 8 8 9 : nach der Sortierung
(0,1) (0,2) (0,3) │ (1,1) (1,2) : vor dem Zusammenführen
(0,1) (1,1) (0,2) (1,2) (0,3) : nach dem Zusammenführen

Siehe auch

führt zwei sortierte Bereiche zusammen
(Algorithmus-Funktionsobjekt)
berechnet die Vereinigung zweier Mengen
(Algorithmus-Funktionsobjekt)
prüft, ob ein Bereich aufsteigend sortiert ist
(Algorithmus-Funktionsobjekt)
sortiert einen Bereich in aufsteigender Reihenfolge
(Algorithmus-Funktionsobjekt)
führt zwei geordnete Bereiche direkt zusammen
(Funktions-Template)