Namensräume
Varianten
Aktionen

std::ranges::merge, std::ranges::merge_result

Von cppreference.com
< cpp‎ | algorithm‎ | ranges
 
 
Algorithmenbibliothek
Beschränkte Algorithmen und Algorithmen für Bereiche (C++20)
Beschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Ausführungsrichtlinien (C++17)
Nicht-modifizierende Sequenzoperationen
Stapeloperationen
(C++17)
Suchoperationen
(C++11)                (C++11)(C++11)

Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Ordnungsändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Zusammenführungsoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikographische Vergleichsoperationen
Permutationsoperationen
C-Bibliothek
Numerische Operationen
Operationen auf uninitialisiertem Speicher
 
Eingeschränkte Algorithmen
Alle Namen in diesem Menü gehören zum Namespace std::ranges
Nicht-modifizierende Sequenzoperationen
Modifizierende Sequenzoperationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen (auf sortierten Bereichen)
       
       
Mengenoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
       
       
Permutationsoperationen
Faltoperationen
Operationen auf uninitialisiertem Speicher
Rückgabetypen
 
Definiert in Header <algorithm>
Aufruf-Signatur
template< std::input_iterator I1, std::sentinel_for<I1> S1,

          std::input_iterator I2, std::sentinel_for<I2> S2,
          std::weakly_incrementable O, class Comp = ranges::less,
          class Proj1 = std::identity, class Proj2 = std::identity >
requires std::mergeable<I1, I2, O, Comp, Proj1, Proj2>
constexpr merge_result<I1, I2, O>
    merge( I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {},

           Proj1 proj1 = {}, Proj2 proj2 = {} );
(1) (seit C++20)
template< ranges::input_range R1, ranges::input_range R2,

          std::weakly_incrementable O, class Comp = ranges::less,
          class Proj1 = std::identity, class Proj2 = std::identity >
requires std::mergeable<ranges::iterator_t<R1>, ranges::iterator_t<R2>,
                        O, Comp, Proj1, Proj2>
constexpr merge_result<ranges::borrowed_iterator_t<R1>,
                       ranges::borrowed_iterator_t<R2>, O>
    merge( R1&& r1, R2&& r2, O result, Comp comp = {},

           Proj1 proj1 = {}, Proj2 proj2 = {} );
(2) (seit C++20)
Hilfstypen
template< class I1, class I2, class O >
using merge_result = ranges::in_in_out_result<I1, I2, O>;
(3) (seit C++20)

Führt zwei *sortierte* Bereiche [[first1last1) und [first2last2) zu einem *sortierten* Bereich zusammen, der bei result beginnt.

Eine Sequenz gilt bezüglich des Komparators comp als *sortiert*, wenn für jeden Iterator it, der auf die Sequenz zeigt, und jede nicht-negative ganze Zahl n, so dass it + n ein gültiger Iterator ist, der auf ein Element der Sequenz zeigt, std::invoke(comp, std::invoke(proj2, *(it + n)), std::invoke(proj1, *it))) zu false ausgewertet wird.

1) Elemente werden mit der gegebenen binären Vergleichsfunktion comp verglichen.
2) Identisch mit (1), aber verwendet r1 als ersten Bereich und r2 als zweiten Bereich, als ob ranges::begin(r1) als first1, ranges::end(r1) als last1, ranges::begin(r2) als first2 und ranges::end(r2) als last2 verwendet würden.

Das Verhalten ist undefiniert, wenn der Zielbereich mit einem der Eingabebereiche überlappt (die Eingabebereiche dürfen sich überlappen).

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

Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithmus-Funktionsobjekte (informell als niebloids bekannt), d.h.

Inhalt

[edit] Parameter

first1, last1 - das Iterator-Sentinel-Paar, das den ersten sortierten Eingabebereich der zu mergenden Elemente definiert
first2, last2 - das Iterator-Sentinel-Paar, das den zweiten sortierten Eingabebereich der zu mergenden Elemente definiert
Ergebnis - der Anfang des Ausgabebereichs
comp - Vergleich, der auf die projizierten Elemente angewendet wird
proj1 - Projektion, die auf die Elemente im ersten Bereich angewendet wird
proj2 - Projektion, die auf die Elemente im zweiten Bereich angewendet wird

[edit] Rückgabewert

{last1, last2, result_last}, wobei result_last das Ende des konstruierten Bereichs ist.

[edit] Komplexität

Höchstens N − 1 Vergleiche und Anwendungen jeder Projektion, wobei N = ranges::distance(first1, last1) + ranges::distance(first2, last12).

[edit] Hinweise

Dieser Algorithmus führt eine ähnliche Aufgabe aus wie ranges::set_union. Beide verbrauchen zwei sortierte Eingabebereiche und erzeugen eine sortierte Ausgabe mit Elementen aus beiden Eingaben. Der Unterschied zwischen diesen beiden Algorithmen liegt im Umgang mit Werten aus beiden Eingabebereichen, die äquivalent verglichen werden (siehe Hinweise zu LessThanComparable). Wenn in dem ersten Bereich n und in dem zweiten Bereich m äquivalente Werte vorkamen, würde ranges::merge alle n + m Vorkommen ausgeben, während ranges::set_union nur max(n, m) Vorkommen ausgeben würde. ranges::merge gibt also genau N Werte aus, während ranges::set_union weniger produzieren kann.

[edit] Mögliche Implementierung

struct merge_fn
{
    template<std::input_iterator I1, std::sentinel_for<I1> S1,
             std::input_iterator I2, std::sentinel_for<I2> S2,
             std::weakly_incrementable O, class Comp = ranges::less,
             class Proj1 = std::identity, class Proj2 = std::identity>
    requires std::mergeable<I1, I2, O, Comp, Proj1, Proj2>
    constexpr ranges::merge_result<I1, I2, O>
        operator()(I1 first1, S1 last1, I2 first2, S2 last2, O result, Comp comp = {},
                   Proj1 proj1 = {}, Proj2 proj2 = {}) const
    {
        for (; !(first1 == last1 or first2 == last2); ++result)
        {
            if (std::invoke(comp, std::invoke(proj2, *first2), std::invoke(proj1, *first1)))
                *result = *first2, ++first2;
            else
                *result = *first1, ++first1;
        }
        auto ret1{ranges::copy(std::move(first1), std::move(last1), std::move(result))};
        auto ret2{ranges::copy(std::move(first2), std::move(last2), std::move(ret1.out))};
        return {std::move(ret1.in), std::move(ret2.in), std::move(ret2.out)};
    }
 
    template<ranges::input_range R1, ranges::input_range R2, std::weakly_incrementable O,
             class Comp = ranges::less,
             class Proj1 = std::identity, class Proj2 = std::identity>
    requires std::mergeable<ranges::iterator_t<R1>, ranges::iterator_t<R2>,
                            O, Comp, Proj1, Proj2>
    constexpr ranges::merge_result<ranges::borrowed_iterator_t<R1>,
                                   ranges::borrowed_iterator_t<R2>, O>
        operator()(R1&& r1, R2&& r2, O result, Comp comp = {},
                   Proj1 proj1 = {}, Proj2 proj2 = {}) const
    {
        return (*this)(ranges::begin(r1), ranges::end(r1),
                       ranges::begin(r2), ranges::end(r2),
                       std::move(result), std::move(comp),
                       std::move(proj1), std::move(proj2));
    }
};
 
inline constexpr merge_fn merge {};

[edit] Beispiel

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
 
void print(const auto& in1, const auto& in2, auto first, auto last)
{
    std::cout << "{ ";
    for (const auto& e : in1)
        std::cout << e << ' ';
    std::cout << "} +\n{ ";
    for (const auto& e : in2)
        std::cout << e << ' ';
    std::cout << "} =\n{ ";
    while (!(first == last))
        std::cout << *first++ << ' ';
    std::cout << "}\n\n";
}
 
int main()
{
    std::vector<int> in1, in2, out;
 
    in1 = {1, 2, 3, 4, 5};
    in2 = {3, 4, 5, 6, 7};
    out.resize(in1.size() + in2.size());
    const auto ret = std::ranges::merge(in1, in2, out.begin());
    print(in1, in2, out.begin(), ret.out);
 
    in1 = {1, 2, 3, 4, 5, 5, 5};
    in2 = {3, 4, 5, 6, 7};
    out.clear();
    out.reserve(in1.size() + in2.size());
    std::ranges::merge(in1, in2, std::back_inserter(out));
    print(in1, in2, out.cbegin(), out.cend());
}

Ausgabe

{ 1 2 3 4 5 } +
{ 3 4 5 6 7 } =
{ 1 2 3 3 4 4 5 5 6 7 }
 
{ 1 2 3 4 5 5 5 } +
{ 3 4 5 6 7 } =
{ 1 2 3 3 4 4 5 5 5 5 6 7 }

[edit] Siehe auch

Führt zwei sortierte Bereiche an Ort und Stelle zusammen
(Algorithmus-Funktionsobjekt)[edit]
Prüft, ob ein Bereich aufsteigend sortiert ist
(Algorithmus-Funktionsobjekt)[edit]
Berechnet die Vereinigung zweier Mengen
(Algorithmus-Funktionsobjekt)[edit]
Sortiert einen Bereich aufsteigend
(Algorithmus-Funktionsobjekt)[edit]
Sortiert einen Bereich von Elementen und behält dabei die Reihenfolge zwischen gleichen Elementen bei
(Algorithmus-Funktionsobjekt)[edit]
Führt zwei sortierte Bereiche zusammen
(Funktionstemplate) [edit]