La pregunta es clara, mi google- y cplusplus.com/reference-fu me están fallando.¿Cuál es la diferencia entre std :: merge y std :: set_union?
Respuesta
set_union solo contendrá elementos que están presentes en ambos juegos una vez. merge los contendrá dos veces.
Ambos funcionan en rangos ordenados y devuelven un resultado ordenado.
'std :: merge' también funciona en rangos ordenados y produce un resultado ordenado. –
@Charkes Bailey: gracias, no había verificado std :: merge y no creía que eso ocurriera. Enmendado mi respuesta. – Mat
Por el bien de todos, tal vez soy yo exigente, pero lo anterior no es lo suficientemente claro para mi gusto. La lectura de esta respuesta * podría * llevarlo a creer que los duplicados son eliminados por set_union() - lo son, aunque no necesariamente en la forma que usted podría pensar. Si el primer rango contiene un elemento equivalente más de una vez, ese elemento aparecerá tantas veces en el rango de salida. Esto se verifica fácilmente: – aho
std::merge
combina todos los elementos, sin eliminar los duplicados, mientras que std::set_union
elimina los duplicados. Es decir, este último aplica la regla de operación union de set theory.
¿Por qué solo estaba pensando en estos algoritmos en términos de un 'std :: set' ... Gracias por la respuesta más limpia y en cortocircuito en mis ojos. – rubenvb
std::merge
mantiene todos los elementos de ambos rangos, elementos equivalentes de la primera gama que preceden a los elementos equivalentes del segundo rango en la salida. Donde aparecen elementos equivalentes en ambos rangos std::set_union
toma solo el elemento del primer rango, de lo contrario, cada elemento se fusiona en orden como en std::merge
.
Referencias: ISO/IEC 14882: 2003 25.3.4 [lib.alg.merge] y 25.3.5.2 [lib.set.union].
esto suena más como intersección, ¿no? – davka
@davka: estoy hablando del comportamiento donde existe un equivalente en el segundo rango. Tomé como leído que todos los elementos sin un equivalente en el otro rango se conservan. He aclarado mi redacción. –
bien, después de leer la oración 5 veces :) Veo a qué te refieres. Lo leí como "solo toma" ... – davka
Esta es la verificación que sugerí en el comentario que publiqué en la respuesta aceptada (es decir, si un elemento está presente en uno de los conjuntos de entrada N veces, aparecerá N veces en la salida de set_union - así que set_union no no eliminar duplicados elementos equivalentes en la forma que nos 'natural' o 'matemática' esperar - Si, sin embargo, ambos de entrada rangos contenían un elemento común de una sola vez, y luego set_union tendríamos aparecerá para eliminar el duplicado)
#include <vector>
#include <algorithm>
#include <iostream>
#include <cassert>
using namespace std;
void printer(int i) { cout << i << ", "; }
int main() {
int mynumbers1[] = { 0, 1, 2, 3, 3, 4 }; // this is sorted, 3 is dupe
int mynumbers2[] = { 5 }; // this is sorted
vector<int> union_result(10);
set_union(mynumbers1, mynumbers1 + sizeof(mynumbers1)/sizeof(int),
mynumbers2, mynumbers2 + sizeof(mynumbers2)/sizeof(int),
union_result.begin());
for_each(union_result.begin(), union_result.end(), printer);
return 0;
}
Esto imprimirá: 0, 1, 2, 3, 3, 4, 5, 0, 0, 0,
Para agregar a las respuestas anteriores, tenga en cuenta que la complejidad de std::set_union
es el doble que la de std::merge
. En la práctica, esto significa que el comparador en std::set_union
se puede aplicar a un elemento después de se ha desreferenciado, mientras que con std::merge
este nunca es el caso.
¿Por qué es importante? Considere algo como:
std::vector<Foo> lhs, rhs;
Y se quiere producir una unión de lhs
y rhs
:
std::set_union(std::cbegin(lhs), std::cend(lhs),
std::cbegin(rhs), std::cend(rhs),
std::back_inserter(union));
Pero ahora supongamos Foo
no es copiable, o es muy caro para copiar y que no es necesario los originales. Usted puede pensar de usar:
std::set_union(std::make_move_iterator(std::begin(lhs)),
std::make_move_iterator(std::end(lhs)),
std::make_move_iterator(std::begin(rhs)),
std::make_move_iterator(std::end(rhs)),
std::back_inserter(union));
pero esto es un comportamiento indefinido ya que hay una posibilidad de un movido Foo
se compara! Por lo tanto, la solución correcta es:
std::merge(std::make_move_iterator(std::begin(lhs)),
std::make_move_iterator(std::end(lhs)),
std::make_move_iterator(std::begin(rhs)),
std::make_move_iterator(std::end(rhs)),
std::back_inserter(union));
union.erase(std::unique(std::begin(union), std::end(union), std::end(union));
que tiene la misma complejidad que std::set_union
.
- 1. ¿Cuál es la diferencia entre std :: valarray y std :: array
- 2. ¿Cuál es la diferencia entre std :: condition_variable y std :: condition_variable_any?
- 3. ¿Cuál es la diferencia entre std :: set y std :: vector?
- 4. ¿Cuál es la diferencia entre std :: string y std :: basic_string? ¿Y por qué se necesitan ambos?
- 5. ¿Cuál es la diferencia entre std :: string :: c_str y std :: string :: data?
- 6. ¿Cuál es la diferencia práctica entre std :: nth_element y std :: sort?
- 7. ¿Cuál es la diferencia entre std :: quick_exit y std :: abort y por qué se necesitó std :: quick_exit?
- 8. std :: merge fusionando dos std :: vector coredump
- 9. ¿Cuál es la diferencia entre persist() y merge() en Hibernate?
- 10. Diferencia: std :: runtime_error vs std :: exception()
- 11. Diferencia entre std :: result_of y decltype
- 12. ¿Cuál es la diferencia entre notify_all() y notify_one() de std :: condition_variable?
- 13. Cuál es la diferencia entre std :: multimap <key, value> y std :: map <key, std :: set <value>>
- 14. ¿Cuán grande es la brecha de rendimiento entre std :: sort y std :: stable_sort en la práctica?
- 15. std :: mem_fun vs std :: mem_fn
- 16. Cómo convertir CString y :: std :: string :: std :: wstring entre sí?
- 17. ¿Existe una diferencia operativa entre std :: set :: iterator y std :: set :: const_iterator?
- 18. std :: this_thread :: yield() vs std :: this_thread :: sleep_for()?
- 19. ¿Cuál es la lógica detrás de std :: bind y std :: thread siempre copiando argumentos?
- 20. ¿Cuál es el propósito de std :: make_pair frente al constructor de std :: pair?
- 21. std :: mapa y std :: unordered_map
- 22. ¿Cuál es la diferencia entre cstdlib y stdlib.h?
- 23. std :: vector versus std :: array en C++
- 24. ¿Cuál es la diferencia entre ssize_t y ptrdiff_t?
- 25. std :: move entre std :: string y std :: vector <unsigned char>
- 26. std :: diferencia de mapa entre llamadas de inserción e índice
- 27. ¿Cuál es la diferencia entre session.Merge y session.SaveOrUpdate?
- 28. ¿Cuál es la diferencia entre printf y std :: ostream debajo de la consola ventanas con UTF-8 salida
- 29. ¿Cuál es la diferencia entre {0} y ""?
- 30. Cuál es la diferencia entre = y: =
http://www.cplusplus.com/reference/algorithm/merge/ http://www.cplusplus.com/reference/algorithm/set_union/ Eso me llevó 10 segundos para encontrarlo. –
@Emilie: Como dije en mi pregunta, eso * no * me proporcionó una respuesta. – rubenvb