Namespaces
Variants

std::merge

с 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









 
Определён в заголовке <algorithm>
template< class InputIt1, class InputIt2, class OutputIt >
OutputIt merge( InputIt1 first1, InputIt1 last1,
                InputIt2 first2, InputIt2 last2,
                OutputIt d_first );
(1) (constexpr начиная с C++20)
template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2, class ForwardIt3 >
ForwardIt3 merge( ExecutionPolicy&& policy,
                  ForwardIt1 first1, ForwardIt1 last1,
                  ForwardIt2 first2, ForwardIt2 last2,
                  ForwardIt3 d_first );
(2) (начиная с C++17)
template< class InputIt1, class InputIt2,
          class OutputIt, class Compare >
OutputIt merge( InputIt1 first1, InputIt1 last1,
                InputIt2 first2, InputIt2 last2,
                OutputIt d_first, Compare comp );
(3) (constexpr начиная с C++20)
template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2,
          class ForwardIt3, class Compare >
ForwardIt3 merge( ExecutionPolicy&& policy,
                  ForwardIt1 first1, ForwardIt1 last1,
                  ForwardIt2 first2, ForwardIt2 last2,
                  ForwardIt3 d_first, Compare comp );
(4) (начиная с C++17)

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

1) Если [first1, last1) или [first2, last2) не является отсортированным относительно operator<(до C++20)std::less{}(начиная с C++20), поведение не определено.
3) Если [first1, last1) или [first2, last2) не отсортированы относительно comp, поведение не определено.
2,4) То же, что и (1,3), но выполняется согласно policy.
Эти перегрузки участвуют в разрешении перегрузки только если значение следующего выражения равно true:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(до C++20)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(начиная с C++20)

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

Если выходной диапазон перекрывается с [first1, last1) или [first2, last2), поведение не определено.

Параметры

first1, last1 - пара итераторов, определяющая первый диапазон элементов для слияния
first2, last2 - пара итераторов, определяющая второй диапазон элементов для слияния
d_first - начало целевого диапазона
policy - политика выполнения для использования
comp - объект функции сравнения (т.е. объект, удовлетворяющий требованиям Compare), который возвращает ​true, если первый аргумент меньше (т.е. упорядочен до) второго.

Сигнатура функции сравнения должна быть эквивалентна следующей:

bool cmp(const Type1& a, const Type2& b);

Хотя сигнатура не обязательно должна содержать const&, функция не должна изменять переданные ей объекты и должна принимать все значения типа (возможно, const) Type1 и Type2 независимо от категории значения (таким образом, Type1& не допускается, также как и Type1 если только Type1 для перемещение эквивалентно копированию(начиная с C++11)).
Типы Type1 и Type2 должны быть такими, что объекты типов InputIt1 и InputIt2 могут быть разыменованы и затем неявно преобразованы как в Type1, так и в Type2. ​

Требования к типам
-
InputIt1, InputIt2 должен соответствовать требованиям LegacyInputIterator.
-
ForwardIt1, ForwardIt2, ForwardIt3 должен соответствовать требованиям LegacyForwardIterator.
-
OutputIt должен соответствовать требованиям LegacyOutputIterator.
-
Compare должен соответствовать требованиям Compare.

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

Выходной итератор на элемент, следующий за последним скопированным.

Сложность

Пусть N1 равно std::distance(first1, last1) и N2 равно std::distance(first2, last2):

1) Не более N1+N2-1 сравнений с использованием operator<(до C++20)std::less{}(начиная с C++20).
2) O(N1+N2) сравнений с использованием operator<(до C++20)std::less{}(начиная с C++20).
3) Не более N1+N2-1 применений функции сравнения comp.
4) O(N1+N2) применений функции сравнения comp.

Исключения

Перегрузки с параметром шаблона ExecutionPolicy сообщают об ошибках следующим образом:

  • Если выполнение функции, вызванной как часть алгоритма, генерирует исключение, и ExecutionPolicy является одной из стандартных политик, вызывается std::terminate. Для любого другого ExecutionPolicy поведение определяется реализацией.
  • Если алгоритму не удаётся выделить память, генерируется std::bad_alloc.

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

См. также реализации в libstdc++ и libc++.

merge (1)
template<class InputIt1, class InputIt2, class OutputIt>
OutputIt merge(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, InputIt2 last2,
               OutputIt d_first)
{
    for (; first1 != last1; ++d_first)
    {
        if (first2 == last2)
            return std::copy(first1, last1, d_first);
        
        if (*first2 < *first1)
        {
            *d_first = *first2;
            ++first2;
        }
        else
        {
            *d_first = *first1;
            ++first1;
        }
    }
    return std::copy(first2, last2, d_first);
}
merge (3)
template<class InputIt1, class InputIt2,
         class OutputIt, class Compare>
OutputIt merge(InputIt1 first1, InputIt1 last1,
               InputIt2 first2, InputIt2 last2,
               OutputIt d_first, Compare comp)
{
    for (; first1 != last1; ++d_first)
    {
        if (first2 == last2)
            return std::copy(first1, last1, d_first);
        
        if (comp(*first2, *first1))
        {
            *d_first = *first2;
            ++first2;
        }
        else
        {
            *d_first = *first1;
            ++first1;
        }
    }
    return std::copy(first2, last2, d_first);
}

Примечания

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

Пример

#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <random>
#include <vector>

auto print = [](const auto rem, const auto& v)
{
    std::cout << rem;
    std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
};

int main()
{
    // fill the vectors with random numbers
    std::random_device rd;
    std::mt19937 mt(rd());
    std::uniform_int_distribution<> dis(0, 9);
    
    std::vector<int> v1(10), v2(10);
    std::generate(v1.begin(), v1.end(), std::bind(dis, std::ref(mt)));
    std::generate(v2.begin(), v2.end(), std::bind(dis, std::ref(mt)));
    
    print("Originally:\nv1: ", v1);
    print("v2: ", v2);
    
    std::sort(v1.begin(), v1.end());
    std::sort(v2.begin(), v2.end());
    
    print("After sorting:\nv1: ", v1);
    print("v2: ", v2);
    
    // merge
    std::vector<int> dst;
    std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));
    
    print("After merging:\ndst: ", dst);
}

Возможный вывод:

Originally:
v1: 2 6 5 7 4 2 2 6 7 0
v2: 8 3 2 5 0 1 9 6 5 0
After sorting:
v1: 0 2 2 2 4 5 6 6 7 7
v2: 0 0 1 2 3 5 5 6 8 9
After merging:
dst: 0 0 0 1 2 2 2 2 3 4 5 5 5 6 6 6 7 7 8 9

Отчёты о дефектах

Следующие отчёты о дефектах, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применён к Поведение, опубликованное ранее Корректное поведение
LWG 780 C++98 операция слияния не была определена определена

См. также

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