Namespaces
Variants

std::merge

von de.cppreference.net
 
 
Algorithmenbibliothek
Eingeschränkte Algorithmen und Algorithmen auf Bereichen (C++20)
Eingeschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Nicht modifizierende Sequenzoperationen    
Batch-Operationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Swap-Operationen
Transformationsoperationen
Erzeugungsoperationen
Entfernungsoperationen
Reihenfolgeändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
(C++11)    

Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Mischoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikografische Vergleichsoperationen
Permutationsoperationen


 
Definiert in Header <algorithm>
template< class InputIt1, class InputIt2, class OutputIt >
OutputIt merge( InputIt1 first1, InputIt1 last1,
                InputIt2 first2, InputIt2 last2,
                OutputIt d_first );
(1) (constexpr seit C++20)
template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2, class ForwardIt3 >
ForwardIt3 merge( ExecutionPolicy&& policy,
                  ForwardIt1 first1, ForwardIt1 last1,
                  ForwardIt2 first2, ForwardIt2 last2,
                  ForwardIt3 d_first );
(2) (seit C++17)
template< class InputIt1, class InputIt2,
          class OutputIt, class Compare >
OutputIt merge( InputIt1 first1, InputIt1 last1,
                InputIt2 first2, InputIt2 last2,
                OutputIt d_first, Compare comp );
(3) (constexpr seit C++20)
template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2,
          class ForwardIt3, class Compare >
ForwardIt3 merge( ExecutionPolicy&& policy,
                  ForwardIt1 first1, ForwardIt1 last1,
                  ForwardIt2 first2, ForwardIt2 last2,
                  ForwardIt3 d_first, Compare comp );
(4) (seit C++17)

Mischt zwei sortierte Bereiche [first1, last1) und [first2, last2) zu einem sortierten Bereich beginnend bei d_first.

1) Wenn [first1, last1) oder [first2, last2) nicht sortiert bezüglich operator<(bis C++20)std::less{}(seit C++20) ist, ist das Verhalten undefiniert.
3) Wenn [first1, last1) oder [first2, last2) nicht sortiert bezüglich comp ist, ist das Verhalten undefiniert.
2,4) Dasselbe wie (1,3), aber ausgeführt gemäß policy.
Diese Überladungen nehmen nur an der Überladungsauflösung teil, wenn der Wert des folgenden Ausdrucks true ist:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(bis C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(seit C++20)

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.

Wenn der Ausgabebereich mit [first1, last1) oder [first2, last2) überlappt, ist das Verhalten undefiniert.

Parameter

first1, last1 - das Paar von Iteratoren, das den ersten Bereich von zu mischenden Elementen definiert
first2, last2 - das Paar von Iteratoren, das den zweiten Bereich von zu mischenden Elementen definiert
d_first - der Beginn des Zielbereichs
policy - die zu verwendende Ausführungsrichtlinie
comp - Vergleichsfunktionsobjekt (d. h. ein Objekt, das die Anforderungen von Compare erfüllt), das true zurückgibt, wenn das erste Argument kleiner ist als (d. h. geordnet vor) das zweite.

Die Signatur der Vergleichsfunktion sollte wie folgt äquivalent sein:

bool cmp(const Type1& a, const Type2& b);

Während die Signatur nicht const& haben muss, darf die Funktion die ihr übergebenen Objekte nicht modifizieren und muss alle Werte vom Typ (möglicherweise const) Type1 und Type2 unabhängig von der Wertkategorie akzeptieren können (daher ist Type1& nicht erlaubt, ebenso wenig Type1 außer wenn für Type1 eine Bewegung äquivalent zu einer Kopie ist(seit C++11)).
Die Typen Type1 und Type2 müssen so sein, dass Objekte der Typen InputIt1 und InputIt2 dereferenziert und dann implizit in sowohl Type1 als auch Type2 konvertiert werden können. ​

Typanforderungen
-
InputIt1, InputIt2 muss die Anforderungen von LegacyInputIterator erfüllen.
-
ForwardIt1, ForwardIt2, ForwardIt3 muss die Anforderungen von LegacyForwardIterator erfüllen.
-
OutputIt muss die Anforderungen von LegacyOutputIterator erfüllen.
-
Compare muss die Anforderungen von Compare erfüllen.

Rückgabewert

Ein Ausgabeiterator, der auf das Element nach dem letzten kopierten Element zeigt.

Komplexität

Gegeben N1 als std::distance(first1, last1) und N2 als std::distance(first2, last2):

1) Höchstens N1+N2-1 Vergleiche unter Verwendung von operator<(bis C++20)std::less{}(seit C++20).
2) O(N1+N2) Vergleiche unter Verwendung von operator<(bis C++20)std::less{}(seit C++20).
3) Höchstens N1+N2-1 Anwendungen der Vergleichsfunktion comp.
4) O(N1+N2) Anwendungen der Vergleichsfunktion comp.

Ausnahmen

Die Überladungen mit einem Vorlagenparameter namens ExecutionPolicy melden Fehler wie folgt:

  • Wenn die Ausführung einer Funktion, die als Teil des Algorithmus aufgerufen wird, eine Ausnahme auslöst und ExecutionPolicy eine der Standardrichtlinien ist, wird std::terminate aufgerufen. Für jedes andere ExecutionPolicy ist das Verhalten implementationsdefiniert.
  • Wenn der Algorithmus keinen Speicher zuweisen kann, wird std::bad_alloc ausgelöst.

Mögliche Implementierung

Siehe auch die Implementierungen in libstdc++ und libc++.

merge (1)
template<class InputIt1, class InputIt2, class OutputIt>
OutputIt merge(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, InputIt2 last2,
               OutputIt d_first)
{
    for (; first1 != last1; ++d_first)
    {
        if (first2 == last2)
            return std::copy(first1, last1, d_first);
        
        if (*first2 < *first1)
        {
            *d_first = *first2;
            ++first2;
        }
        else
        {
            *d_first = *first1;
            ++first1;
        }
    }
    return std::copy(first2, last2, d_first);
}
merge (3)
template<class InputIt1, class InputIt2,
         class OutputIt, class Compare>
OutputIt merge(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, InputIt2 last2,
               OutputIt d_first, Compare comp)
{
    for (; first1 != last1; ++d_first)
    {
        if (first2 == last2)
            return std::copy(first1, last1, d_first);
        
        if (comp(*first2, *first1))
        {
            *d_first = *first2;
            ++first2;
        }
        else
        {
            *d_first = *first1;
            ++first1;
        }
    }
    return std::copy(first2, last2, d_first);
}

Anmerkungen

Dieser Algorithmus führt eine ähnliche Aufgabe aus wie std::set_union. Beide verbrauchen zwei sortierte Eingabebereiche und erzeugen eine sortierte Ausgabe mit Elementen aus beiden Eingaben. Der Unterschied zwischen diesen beiden Algorithmen besteht in der Behandlung von Werten aus beiden Eingabebereichen, die äquivalent vergleichen (siehe Anmerkungen zu LessThanComparable). Wenn äquivalente Werte n Mal im ersten Bereich und m Mal im zweiten vorkamen, würde std::merge alle n + m Vorkommen ausgeben, während std::set_union nur std::max(n, m) ausgeben würde. Also gibt std::merge genau std::distance(first1, last1) + std::distance(first2, last2) Werte aus und std::set_union kann weniger erzeugen.

Beispiel

#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <random>
#include <vector>

auto print = [](const auto rem, const auto& v)
{
    std::cout << rem;
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
};

int main()
{
    // fill the vectors with random numbers
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_int_distribution<> dis(0, 9);
    
    std::vector<int> v1(10), v2(10);
    std::generate(v1.begin(), v1.end(), std::bind(dis, std::ref(mt)));
    std::generate(v2.begin(), v2.end(), std::bind(dis, std::ref(mt)));
    
    print("Originally:\nv1: ", v1);
    print("v2: ", v2);
    
    std::sort(v1.begin(), v1.end());
    std::sort(v2.begin(), v2.end());
    
    print("After sorting:\nv1: ", v1);
    print("v2: ", v2);
    
    // merge
    std::vector<int> dst;
    std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));
    
    print("After merging:\ndst: ", dst);
}

Mögliche Ausgabe:

Originally:
v1: 2 6 5 7 4 2 2 6 7 0
v2: 8 3 2 5 0 1 9 6 5 0
After sorting:
v1: 0 2 2 2 4 5 6 6 7 7
v2: 0 0 1 2 3 5 5 6 8 9
After merging:
dst: 0 0 0 1 2 2 2 2 3 4 5 5 5 6 6 6 7 7 8 9

Fehlerberichte

Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR Angewendet auf Verhalten wie veröffentlicht Richtiges Verhalten
LWG 780 C++98 die Mischoperation war nicht definiert definiert

Siehe auch

mischt zwei geordnete Bereiche direkt
(Funktionstemplate & Algorithmus-Funktionsobjekt)
(C++11)
prüft, ob ein Bereich sortiert ist
(Funktionstemplate & Algorithmus-Funktionsobjekt)
berechnet die Vereinigung zweier Mengen
(Funktionstemplate & Algorithmus-Funktionsobjekt)
sortiert einen Bereich von Elementen
(Funktionstemplate & Algorithmus-Funktionsobjekt)
sortiert einen Bereich von Elementen, während die relative Reihenfolge äquivalenter Elemente erhalten bleibt
(Funktionstemplate & Algorithmus-Funktionsobjekt)
mischt zwei sortierte Bereiche
(Algorithmus-Funktionsobjekt)