std::merge
| Défini dans l'en-tête <algorithm>
|
||
template< class InputIt1, class InputIt2, class OutputIt >
OutputIt merge( InputIt1 first1, InputIt1 last1,
InputIt2 first2, InputIt2 last2,
OutputIt d_first );
|
(1) | (constexpr depuis 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) | (depuis 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 depuis 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) | (depuis C++17) |
Fusionne deux plages triées [first1, last1) et [first2, last2) en une seule plage triée commençant à d_first.
[first1, last1) ou [first2, last2) n'est pas trié par rapport à operator<(jusqu'à C++20)std::less{}(depuis C++20), le comportement est indéfini.[first1, last1) ou [first2, last2) n'est pas trié par rapport à comp, le comportement est indéfini.policy.true :
|
|
(jusqu'à C++20) |
|
|
(depuis C++20) |
Cette fonction de fusion est stable, ce qui signifie que pour les éléments équivalents dans les deux plages originales, les éléments de la première plage (en conservant leur ordre original) précèdent les éléments de la seconde plage (en conservant leur ordre original).
Si la plage de sortie chevauche [first1, last1) ou [first2, last2), le comportement est indéfini.
Paramètres
| first1, last1 | - | la paire d'itérateurs définissant la première plage d'éléments à fusionner |
| first2, last2 | - | la paire d'itérateurs définissant la seconde plage d'éléments à fusionner |
| d_first | - | le début de la plage de destination |
| policy | - | la politique d'exécution à utiliser |
| comp | - | objet fonction de comparaison (c'est-à-dire un objet qui satisfait les exigences de Compare) qui retourne truetrue si le premier argument est inférieur au second (c'est-à-dire est ordonné avant).
La signature de la fonction de comparaison devrait être équivalente à la suivante :
|
| . | ||
Exigences de type
InputIt1, InputIt2- doit satisfaire les exigences de LegacyInputIterator | ||
.
ForwardIt1, ForwardIt2, ForwardIt3- doit satisfaire les exigences de LegacyForwardIterator | ||
.
OutputIt- doit satisfaire les exigences de LegacyOutputIterator | ||
.
Compare- doit satisfaire les exigences de Compare | ||
.
Valeur de retour
Un itérateur de sortie pointant sur l'élément après le dernier élément copié.
Complexité\(\scriptsize N_1\)N1std::distance(first1, last1) comme \(\scriptsize N_2\)N2std::distance(first2, last2) comme
operator< comparaisons utilisant std::less{}(jusqu'à C++20)(depuis C++20)operator< comparaisons utilisant std::less{}(jusqu'à C++20)(depuis C++20)comp applications de la fonction de comparaison comp applications de la fonction de comparaison .
ExceptionsExecutionPolicyLes surcharges avec un paramètre template nommé
- signalent les erreurs comme suit :
ExecutionPolicySi l'exécution d'une fonction invoquée dans le cadre de l'algorithme lève une exception et que est l'une des politiques standard, std::terminateExecutionPolicyest appelé. Pour tout autre - , le comportement est défini par l'implémentation.Si l'algorithme échoue à allouer de la mémoire, std::bad_alloc
est lancée.
Implémentation possibleVoir aussi les implémentations dans libstdc++ et libc++
| . |
|---|
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 (1) |
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);
}
|
merge (3)
Notesstd::set_unionCet algorithme effectue une tâche similaire à celle de fait. Les deux consomment deux plages d'entrée triées et produisent une sortie triée avec les éléments des deux entrées. La différence entre ces deux algorithmes réside dans la gestion des valeurs des deux plages d'entrée qui se comparent comme équivalentes (voir les notes sur LessThanComparablen). Si des valeurs équivalentes apparaissaient m fois dans la première plage et std::merge fois dans la seconde, n + m produirait toutes les std::set_union occurrences tandis que std::max(n, m) ne produirait que std::merge occurrences. Ainsi std::distance(first1, last1) + std::distance(first2, last2) produit exactement std::set_union valeurs et
peut en produire moins.
#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);
}
Exécuter ce code
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
Sortie possible :
Rapports de défauts
| Les rapports de défauts suivants modifiant le comportement ont été appliqués rétroactivement aux normes C++ précédemment publiées. | DR | Appliqué à | Comportement publié |
|---|---|---|---|
| Comportement correct | LWG 780 | C++98 | l'opération de fusion n'était pas définie |
définie
| inplace_merge fusionne deux plages ordonnées sur place&(fonction template | |
ranges::inplace_merge |
|
is_sorted |
(C++11) vérifie si une plage est triée&(fonction template |
ranges::is_sorted |
|
| set_union calcule l'union de deux ensembles&(fonction template | |
ranges::set_union |
|
| sort trie une plage d'éléments&(fonction template | |
ranges::sort |
|
| stable_sort trie une plage d'éléments tout en préservant l'ordre relatif entre éléments équivalents&(fonction template | |
ranges::stable_sort |
|
ranges::merge |
(C++20) fusionne deux plages triées |