Namespaces
Variants

std::ranges::merge, std::ranges::merge_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 merge_result<I1, I2, O>
    merge( 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 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) (начиная с C++20)
Вспомогательные типы
template< class I1, class I2, class O >
using merge_result = ranges::in_in_out_result<I1, I2, O>;
(3) (начиная с C++20)

Объединяет два отсортированных диапазона [[first1, last1) и [first2, last2) в один отсортированный диапазон, начинающийся с result.

Последовательность считается отсортированной относительно компаратора comp если для любого итератора it указывающего на последовательность и любого неотрицательного целого числа n такого, что it + n является допустимым итератором, указывающим на элемент последовательности, std::invoke(comp, std::invoke(proj2, *(it + n)), std::invoke(proj1, *it))) вычисляется в false.

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 элементов для слияния
result - начало выходного диапазона
comp - функция сравнения, применяемая к проецируемым элементам
proj1 - проекция, применяемая к элементам в первом диапазоне
proj2 - проекция, применяемая к элементам во втором диапазоне

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

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

Сложность

Не более N − 1 сравнений и применений каждой проекции, где N = ranges:: distance ( first1, last1 ) + ranges:: distance ( first2, last12 ) .

Примечания

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

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

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

Пример

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

Вывод:

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

См. также

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