Namespaces
Variants

std::ranges::set_union, std::ranges::set_union_result

Из ru.cppreference.net
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы для диапазонов (C++20)
Ограниченные алгоритмы, например, ranges::copy, ranges::sort, ...
Неизменяющие операции над последовательностями    
Пакетные операции
(C++17)
Операции поиска
Изменяющие операции над последовательностями
Операции копирования
(C++11)
(C++11)
Операции обмена
Операции преобразования
Операции генерации
Операции удаления
Операции изменения порядка
(до C++17)(C++11)
(C++20)(C++20)
Операции выборки
(C++17)

Сортировка и связанные операции
Операции разбиения
(C++11)    

Операции сортировки
Операции бинарного поиска
(на разбитых диапазонах)
Операции над множествами (на отсортированных диапазонах)
Операции слияния (на отсортированных диапазонах)
Операции с кучей
Операции поиска минимума/максимума
(C++11)
(C++17)
Операции лексикографического сравнения
Операции перестановки


Политики выполнения (C++17)
(только для пояснения*)(C++26)

Численные операции
(C++11)
(C++17)
(C++17)    

Специализированные <memory>алгоритмы

Специализированные <random>алгоритмы
Библиотека C









 
Ограниченные алгоритмы
Все имена в этом меню принадлежат пространству имён std::ranges
Неизменяющие операции над последовательностями
Изменяющие операции над последовательностями
Операции разбиения
Операции сортировки
Операции бинарного поиска (на отсортированных диапазонах)
       
       
Операции над множествами (на отсортированных диапазонах)
Операции с кучей
Операции поиска минимума/максимума
       
       
Операции перестановки
Операции свёртки
Операции с неинициализированной памятью
Типы возврата
 
Определён в заголовке <algorithm>
Сигнатура вызова
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) (начиная с 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) (начиная с C++20)
Вспомогательные типы
template< class I1, class I2, class O >
using set_union_result = ranges::in_in_out_result<I1, I2, O>;
(3) (начиная с C++20)

Строит отсортированное объединение, начиная с result состоящее из множества элементов, присутствующих в одном или обоих отсортированных входных диапазонах [first1, last1) и [first2, last2).

Если некоторый элемент найден m раз в [first1, last1) и n раза в [first2, last2), то все m элементов будут скопированы из [first1, last1) в result, сохраняя порядок, а затем ровно max(n - m, 0) элементов будут скопированы из [first2, last2) в result, также сохраняя порядок.

Поведение не определено, если

  • входные диапазоны не отсортированы относительно comp и proj1 или proj2, соответственно, или
  • результирующий диапазон перекрывается с любым из входных диапазонов.
1) Элементы сравниваются с помощью заданной бинарной функции сравнения comp.
2) То же, что и (1), но использует r1 как первый диапазон и r2 как второй диапазон, как если бы использовал ranges::begin(r1) как first1, ranges::end(r1) как last1, ranges::begin(r2) как first2 и ranges::end(r2) как last2.

Функциональные объекты, описанные на этой странице, являются объектами-функциями алгоритмов (неофициально известными как niebloids), то есть:

Параметры

first1, last1 - пара итератор-страж, определяющая первый входной отсортированный range элементов
first2, last2 - пара итератор-страж, определяющая второй входной отсортированный range элементов
r1 - первый входной отсортированный диапазон
r2 - второй входной отсортированный диапазон
result - начало выходного диапазона
comp - сравнение, применяемое к проецируемым элементам
proj1 - проекция, применяемая к элементам первого диапазона
proj2 - проекция, применяемая к элементам второго диапазона

Возвращаемое значение

{ last1, last2, result_last } , где result_last является концом построенного диапазона.

Сложность

Не более 2·(N 1 +N 2 )-1 сравнений и применений каждой проекции, где N 1 и N 2 являются ranges:: distance ( first1, last1 ) и ranges:: distance ( first2, last2 ) соответственно.

Примечания

Этот алгоритм выполняет схожую задачу с ranges::merge . Оба обрабатывают два отсортированных входных диапазона и выдают отсортированный выходной диапазон с элементами из обоих входов. Разница между этими двумя алгоритмами заключается в обработке значений из обоих входных диапазонов, которые сравниваются как эквивалентные (см. примечания к LessThanComparable ). Если любые эквивалентные значения появлялись n раз в первом диапазоне и m раз во втором, ranges::merge вывел бы все n + m вхождений, тогда как ranges::set_union вывел бы только std:: max ( n, m ) . Таким образом, ranges::merge выдает ровно (N 1 +N 2 ) значений, а ranges::set_union может выдать меньше.

Возможная реализация

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 {};

Пример

#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());
}

Вывод:

{ 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 }

См. также

вычисляет разность двух множеств
(объект функции алгоритма)
вычисляет пересечение двух множеств
(объект функции алгоритма)
вычисляет симметрическую разность двух множеств
(объект функции алгоритма)
объединяет два отсортированных диапазона
(объект функции алгоритма)
определяет, является ли одна последовательность подпоследовательностью другой
(объект функции алгоритма)
вычисляет объединение двух множеств
(шаблон функции)