std::merge
| Определён в заголовке <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.
[first1, last1) или [first2, last2) не является отсортированным относительно operator<(до C++20)std::less{}(начиная с C++20), поведение не определено.[first1, last1) или [first2, last2) не отсортированы относительно comp, поведение не определено.policy.true:
|
|
(до C++20) |
|
|
(начиная с C++20) |
Эта функция слияния является устойчивой, что означает, что для эквивалентных элементов из исходных двух диапазонов элементы из первого диапазона (сохраняя их исходный порядок) предшествуют элементам из второго диапазона (сохраняя их исходный порядок).
Если выходной диапазон перекрывается с [first1, last1) или [first2, last2), поведение не определено.
Параметры
| first1, last1 | - | пара итераторов, определяющая первый диапазон элементов для слияния |
| first2, last2 | - | пара итераторов, определяющая второй диапазон элементов для слияния |
| d_first | - | начало целевого диапазона |
| policy | - | политика выполнения для использования |
| comp | - | объект функции сравнения (т.е. объект, удовлетворяющий требованиям Compare), который возвращает true, если первый аргумент меньше (т.е. упорядочен до) второго. Сигнатура функции сравнения должна быть эквивалентна следующей:
Хотя сигнатура не обязательно должна содержать |
| Требования к типам | ||
-InputIt1, InputIt2 должен соответствовать требованиям LegacyInputIterator.
| ||
-ForwardIt1, ForwardIt2, ForwardIt3 должен соответствовать требованиям LegacyForwardIterator.
| ||
-OutputIt должен соответствовать требованиям LegacyOutputIterator.
| ||
-Compare должен соответствовать требованиям Compare.
| ||
Возвращаемое значение
Выходной итератор на элемент, следующий за последним скопированным.
Сложность
Пусть N1 равно std::distance(first1, last1) и N2 равно std::distance(first2, last2):
operator<(до C++20)std::less{}(начиная с C++20).operator<(до C++20)std::less{}(начиная с C++20).comp.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++20) |
|
(C++11) |
проверяет, отсортирован ли диапазон (шаблон функции & функциональный объект алгоритма) |
(C++20) |
|
| вычисляет объединение двух множеств (шаблон функции & функциональный объект алгоритма) | |
(C++20) |
|
| сортирует диапазон элементов (шаблон функции & функциональный объект алгоритма) | |
(C++20) |
|
| сортирует диапазон элементов, сохраняя относительный порядок эквивалентных элементов (шаблон функции & функциональный объект алгоритма) | |
(C++20) |
|
(C++20) |
объединяет два отсортированных диапазона (функциональный объект алгоритма) |