std::ranges::set_union, std::ranges::set_union_result
| Défini dans l'en-tête <algorithm>
|
||
| Signature d'appel |
||
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) | (depuis 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) | (depuis C++20) |
| Types auxiliaires |
||
template< class I1, class I2, class O >
using set_union_result = ranges::in_in_out_result<I1, I2, O>;
|
(3) | (depuis C++20) |
Construit une union triée commençant à result composée de l'ensemble des éléments présents dans l'une des deux plages d'entrée triées ou dans les deux [first1, last1) et [first2, last2).
Si un élément est trouvé m fois dans [first1, last1) et n fois dans [first2, last2), alors tous les m éléments seront copiés de [first1, last1) à result, en préservant l'ordre, puis exactement max(n - m, 0) éléments seront copiés de [first2, last2) à result, également en préservant l'ordre.
Le comportement est indéfini si
- les plages d'entrée ne sont pas triées par rapport à
competproj1ouproj2, respectivement, ou - la plage résultante chevauche l'une des plages d'entrée.
comp.r1 comme première plage et r2 comme deuxième plage, comme si ranges::begin(r1) était utilisé comme first1, ranges::end(r1) comme last1, ranges::begin(r2) comme first2, et ranges::end(r2) comme last2.Les entités de type fonction décrites sur cette page sont des objets fonction d'algorithme (informellement connus sous le nom de niebloids), c'est-à-dire :
- Les listes d'arguments de modèle explicites ne peuvent pas être spécifiées lors de l'appel de l'une d'entre elles.
- Aucune d'elles n'est visible par recherche dépendante des arguments.
- Lorsque l'une d'elles est trouvée par recherche non qualifiée normale comme le nom à gauche de l'opérateur d'appel de fonction, recherche dépendante des arguments est inhibée.
Paramètres
| first1, last1 | - | la paire itérateur-sentinelle définissant la première plage triée d'éléments en entrée |
| first2, last2 | - | la paire itérateur-sentinelle définissant la deuxième plage triée d'éléments en entrée |
| r1 | - | la première plage triée en entrée |
| r2 | - | la deuxième plage triée en entrée |
| result | - | le début de la plage de sortie |
| comp | - | comparaison à appliquer aux éléments projetés |
| proj1 | - | projection à appliquer aux éléments de la première plage |
| proj2 | - | projection à appliquer aux éléments de la deuxième plage |
Valeur de retour
{ last1, last2, result_last } , où result_last est la fin de la plage construite.
Complexité
Au plus 2·(N 1 +N 2 )-1 comparaisons et applications de chaque projection, où N 1 et N 2 sont ranges:: distance ( first1, last1 ) et ranges:: distance ( first2, last2 ) , respectivement.
Notes
Cet algorithme effectue une tâche similaire à
ranges::merge
. Les deux consomment deux plages d'entrée triées et produisent une sortie triée avec des éléments des deux entrées. La différence entre ces deux algorithmes réside dans le traitement des valeurs des deux plages d'entrée qui sont équivalentes en comparaison (voir les notes sur
LessThanComparable
). Si des valeurs équivalentes apparaissaient
n
fois dans la première plage et
m
fois dans la seconde,
ranges::merge
produirait toutes les
n
+
m
occurrences tandis que
ranges::set_union
produirait seulement
std::
max
(
n, m
)
occurrences. Ainsi
ranges::merge
produit exactement
(N
1
+N
2
)
valeurs et
ranges::set_union
peut en produire moins.
Implémentation possible
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 {}; |
Exemple
#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()); }
Sortie :
{ 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 }
Voir aussi
(C++20) |
calcule la différence entre deux ensembles (objet fonction d'algorithme) |
(C++20) |
calcule l'intersection de deux ensembles (objet fonction d'algorithme) |
| calcule la différence symétrique entre deux ensembles (objet fonction d'algorithme) | |
(C++20) |
fusionne deux plages triées (objet fonction d'algorithme) |
(C++20) |
détermine si une séquence est une sous-séquence d'une autre (objet fonction d'algorithme) |
| calcule l'union de deux ensembles (gabarit de fonction) |