std::ranges::set_union, std::ranges::set_union_result
| 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_union_result<I1, I2, O>
set_union( 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_union_result<ranges::borrowed_iterator_t<R1>,
ranges::borrowed_iterator_t<R2>, O>
set_union( 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 set_union_result = ranges::in_in_out_result<I1, I2, O>;
|
(3) | (seit C++20) |
Erstellt eine sortierte Vereinigung beginnend bei result bestehend aus der Menge von Elementen, die in einem oder beiden sortierten Eingabebereichen [first1, last1) und [first2, last2) vorhanden sind.
Wenn ein Element m mal in [first1, last1) und n mal in [first2, last2) gefunden wird, dann werden alle m Elemente aus [first1, last1) nach result kopiert, wobei die Reihenfolge erhalten bleibt, und danach werden genau max(n - m, 0) Elemente aus [first2, last2) nach result kopiert, ebenfalls unter Beibehaltung der Reihenfolge.
Das Verhalten ist undefiniert, wenn
- die Eingabebereiche nicht bezüglich
compundproj1bzw.proj2sortiert sind, oder - der Ergebnisbereich mit einem der Eingabebereiche überlappt.
comp verglichen.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 bekannt als Niebloids), das heißt:
- Explizite Template-Argumentlisten können beim Aufruf einer von ihnen nicht angegeben werden.
- Keine von ihnen ist für die argumentabhängige Namenssuche sichtbar.
- Wenn eine von ihnen durch normale unqualifizierte Namenssuche als Name links vom Funktionsaufrufoperator gefunden wird, wird die argumentabhängige Namenssuche unterdrückt.
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 | - | 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 |
Rückgabewert
{ last1, last2, 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.
Hinweise
Dieser Algorithmus führt eine ähnliche Aufgabe aus wie
ranges::merge
es tut. Beide verarbeiten 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 als äquivalent verglichen werden (siehe Anmerkungen zu
LessThanComparable
). Wenn äquivalente Werte
n
-mal im ersten Bereich und
m
-mal im zweiten Bereich auftreten, würde
ranges::merge
alle
n
+
m
Vorkommen ausgeben, während
ranges::set_union
nur
std::
max
(
n, m
)
Vorkommen ausgeben würde. Daher gibt
ranges::merge
exakt
(N
1
+N
2
)
Werte aus, und
ranges::set_union
kann weniger erzeugen.
Mögliche Implementierung
struct set_union_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_union_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(proj1, *first1), std::invoke(proj2, *first2))) { *result = *first1; ++first1; } else if (std::invoke(comp, std::invoke(proj2, *first2), std::invoke(proj1, *first1))) { *result = *first2; ++first2; } else { *result = *first1; ++first1; ++first2; } } auto res1 = ranges::copy(std::move(first1), std::move(last1), std::move(result)); auto res2 = ranges::copy(std::move(first2), std::move(last2), std::move(res1.out)); return {std::move(res1.in), std::move(res2.in), std::move(res2.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::set_union_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 set_union_fn set_union {}; |
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 << "} ∪ { "; 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::set_union(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::set_union(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 4 5 6 7 }
{ 1 2 3 4 5 5 5 } ∪ { 3 4 5 6 7 } =
{ 1 2 3 4 5 5 5 6 7 }
Siehe auch
(C++20) |
berechnet die Differenz zwischen zwei Mengen (Algorithmus-Funktionsobjekt) |
(C++20) |
berechnet die Schnittmenge zweier Mengen (Algorithmus-Funktionsobjekt) |
| berechnet die symmetrische Differenz zwischen zwei Mengen (Algorithmus-Funktionsobjekt) | |
(C++20) |
vereinigt zwei sortierte Bereiche (Algorithmus-Funktionsobjekt) |
(C++20) |
bestimmt, ob eine Sequenz eine Untersequenz einer anderen ist (Algorithmus-Funktionsobjekt) |
| berechnet die Vereinigungsmenge zweier Mengen (Funktionsschablone) |