std::merge
| 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.
[first1, last1) oder [first2, last2) nicht sortiert bezüglich operator<(bis C++20)std::less{}(seit C++20) ist, ist das Verhalten undefiniert.[first1, last1) oder [first2, last2) nicht sortiert bezüglich comp ist, ist das Verhalten undefiniert.policy.true ist:
|
|
(bis C++20) |
|
|
(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:
Während die Signatur nicht |
| 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):
operator<(bis C++20)std::less{}(seit C++20).operator<(bis C++20)std::less{}(seit C++20).comp.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
ExecutionPolicyeine der Standardrichtlinien ist, wird std::terminate aufgerufen. Für jedes andereExecutionPolicyist 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++20) |
|
(C++11) |
prüft, ob ein Bereich sortiert ist (Funktionstemplate & Algorithmus-Funktionsobjekt) |
(C++20) |
|
| berechnet die Vereinigung zweier Mengen (Funktionstemplate & Algorithmus-Funktionsobjekt) | |
(C++20) |
|
| sortiert einen Bereich von Elementen (Funktionstemplate & Algorithmus-Funktionsobjekt) | |
(C++20) |
|
| sortiert einen Bereich von Elementen, während die relative Reihenfolge äquivalenter Elemente erhalten bleibt (Funktionstemplate & Algorithmus-Funktionsobjekt) | |
(C++20) |
|
(C++20) |
mischt zwei sortierte Bereiche (Algorithmus-Funktionsobjekt) |