Namespaces
Variants

std::ranges::set_difference, std::ranges::set_difference_result

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    
Stapeloperationen
(C++17)
Suchoperationen
Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
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


 
Eingeschränkte Algorithmen
Alle Namen in diesem Menü gehören zum Namensraum std::ranges
Nicht modifizierende Sequenzoperationen
Modifizierende Sequenzoperationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen (auf sortierten Bereichen)
       
       
Mengenoperationen (auf sortierten Bereichen)
Heap-Operationen
Minimum/Maximum-Operationen
       
       
Permutationsoperationen
Faltungsoperationen
Numerische Operationen
(C++23)            
Operationen auf nicht initialisiertem Speicher
Rückgabetypen
 
Definiert in Header <algorithm>
Aufrufsignatur
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 set_difference_result<I1, O>
    set_difference( 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 set_difference_result<ranges::borrowed_iterator_t<R1>, O>
    set_difference( R1&& r1, R2&& r2, O result, Comp comp = {},
                    Proj1 proj1 = {}, Proj2 proj2 = {} );
(2) (seit C++20)
Hilfstypen
template< class I, class O >
using set_difference_result = ranges::in_out_result<I, O>;
(3) (seit C++20)

Kopiert die Elemente aus dem sortierten Eingabebereich [first1, last1), die im sortierten Eingabebereich [first2, last2) nicht gefunden werden, in den Ausgabebereich, der bei result beginnt.

Das Verhalten ist undefiniert, wenn

  • die Eingabebereiche nicht in Bezug auf comp und proj1 bzw. proj2 sortiert sind, oder
  • der resultierende Bereich einen der Eingabebereiche überlappt.
1) Elemente werden mit der angegebenen binären Vergleichsfunktion comp verglichen.
2) Gleich wie (1), verwendet jedoch 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.

Die auf dieser Seite beschriebenen funktionsähnlichen Entitäten sind Algorithmus-Funktionsobjekte (informell als Niebloids bekannt), das heißt:

Parameter

first1, last1 - das Iterator-Sentinel-Paar, das den ersten sortierten Eingabe- Bereich von Elementen definiert
first2, last2 - das Iterator-Sentinel-Paar, das den zweiten sortierten Eingabe- Bereich von Elementen definiert
r1 - der erste sortierte Eingabebereich
r2 - der zweite sortierte Eingabebereich
result - der Anfang des Ausgabebereichs
comp - Komparator, 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

Rückgabewert

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

Komplexität

Höchstens 2·(N 1 +N 2 )-1 Vergleiche und Anwendungen jeder Projektion, wobei N 1 und N 2 jeweils ranges:: distance ( first1, last1 ) und ranges:: distance ( first2, last2 ) entsprechen.

Mögliche Implementierung

struct set_difference_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::set_difference_result<I1, O>
        operator()(I1 first1, S1 last1, I2 first2, S2 last2,
                   O result, Comp comp = {},
                   Proj1 proj1 = {}, Proj2 proj2 = {}) const
    {
        while (!(first1 == last1 or first2 == last2))
        {
            if (std::invoke(comp, std::invoke(proj1, *first1), std::invoke(proj2, *first2)))
            {
                *result = *first1;
                ++first1;
                ++result;
            }
            else if (std::invoke(comp, std::invoke(proj2, *first2),
                                 std::invoke(proj1, *first1)))
                ++first2;
            else
            {
                ++first1;
                ++first2;
            }
        }
        return ranges::copy(std::move(first1), std::move(last1), std::move(result));
    }
    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::set_difference_result<ranges::borrowed_iterator_t<R1>, 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 set_difference_fn set_difference {};

Beispiel

#include <algorithm>
#include <cassert>
#include <iostream>
#include <iterator>
#include <string_view>
#include <vector>
auto print = [](const auto& v, std::string_view end = "")
{
    std::cout << "{ ";
    for (auto n{v.size()}; auto i : v)
        std::cout << i << (--n ? ", " : " ");
    std::cout << "} " << end;
};
struct Order // eine Struktur mit sehr interessanten Daten
{
    int order_id{};
    friend std::ostream& operator<<(std::ostream& os, const Order& ord)
    {
        return os << '{' << ord.order_id << '}';
    }
};
int main()
{
    const auto v1 = {1, 2, 5, 5, 5, 9};
    const auto v2 = {2, 5, 7};
    std::vector<int> diff{};
    std::ranges::set_difference(v1, v2, std::back_inserter(diff));
    print(v1, "∖ ");
    print(v2, "= ");
    print(diff, "\n\n");
    // Wir möchten wissen, welche Bestellungen zwischen altem und neuem Zustand "herausgeschnitten" werden:
    const std::vector<Order> old_orders{{1}, {2}, {5}, {9}};
    const std::vector<Order> new_orders{{2}, {5}, {7}};
    std::vector<Order> cut_orders(old_orders.size() + new_orders.size());
    auto [old_orders_end, cut_orders_last] =
        std::ranges::set_difference(old_orders, new_orders,
                                    cut_orders.begin(), {},
                                    &Order::order_id, &Order::order_id);
    assert(old_orders_end == old_orders.end());
    std::cout << "old orders = ";
    print(old_orders, "\n");
    std::cout << "new orders = ";
    print(new_orders, "\n");
    std::cout << "cut orders = ";
    print(cut_orders, "\n");
    cut_orders.erase(cut_orders_last, end(cut_orders));
    std::cout << "cut orders = ";
    print(cut_orders, "\n");
}

Ausgabe:

{ 1, 2, 5, 5, 5, 9 } ∖ { 2, 5, 7 } = { 1, 5, 5, 9 } 
old orders = { {1}, {2}, {5}, {9} } 
new orders = { {2}, {5}, {7} } 
cut orders = { {1}, {9}, {0}, {0}, {0}, {0}, {0} } 
cut orders = { {1}, {9} }

Siehe auch

berechnet die Vereinigung zweier Mengen
(Algorithmus-Funktionsobjekt)
berechnet die Schnittmenge zweier Mengen
(Algorithmus-Funktionsobjekt)
berechnet die symmetrische Differenz zweier Mengen
(Algorithmus-Funktionsobjekt)
bestimmt, ob eine Folge eine Teilfolge einer anderen ist
(Algorithmus-Funktionsobjekt)
berechnet die Differenz zweier Mengen
(Funktionstemplate)