2010-08-19 10 views

Respuesta

37

remove [...] pone los elementos 'retirados' al principio de la secuencia de

¿Qué? No. Tanto remove_if como partition ponen primero los elementos "buenos". partition pone los elementos "malos" después de eso, mientras que remove_if no especifica lo que viene después - pueden ser los elementos malos, pero también pueden ser copias de cualquier elemento (ya sea bueno o malo).

Por ejemplo, si partition 1 2 3 4 5 en incluso, es posible obtener 2 4 5 3 1 (tenga en cuenta que cada elemento se produce una sola vez), mientras que si remove_if los impares elementos, es posible que obtener 2 4 3 4 5 (tenga en cuenta los duplicados).

+0

gracias, entendí que –

2

De La biblioteca C++ estándar: un tutorial y de referencia

remove() - Elimina los elementos con un valor dado, lógicamente única sobreescribiéndolos con los elementos siguientes que no fueron extraídas. No cambie la cantidad de elementos en los rangos en los que operan. En lugar de ello, vuelven la posición de la nueva "final" de la gama

partición() - Cambia el orden de los elementos de modo que los elementos que coinciden con un criterio están en el frente

stable_partition() - Igual partición(), pero conserva el orden relativo de juego y elementos que no coinciden

+0

buena explicación. – Chubsdad

-1

partición - "grupos" los elementos de un recipiente de acuerdo con un cierto predicado (por ejemplo, números pares e impares en un std :: vector)

eliminar - elimina un certificado un valor de un contenedor; de hecho elementos se mueven a la extremo del recipiente inicial, un iterador al nuevo extremo se devuelve y los elementos "eliminado" son todavía accesibles

EDIT:

remove - elimina un cierto valor de un recipiente; los elementos NO se mueven al final del contenedor inicial como se indicó anteriormente, se devuelve un iterador al nuevo extremo pero los iteradores en el rango [newEnd, last) son aún referenciables, por lo tanto accesibles, PERO los elementos a los que apuntan no están especificados.

+0

Eso es incorrecto, eliminar sobrescribe los elementos 'eliminados' por los siguientes, por lo que no todos ellos podrían ser accesibles después ... – MartinStettner

+0

Me gustaría saber cuál es el problema con mi respuesta si es posible. Quizás aprenda algo en el proceso. – celavek

+0

@MartinStettner Creo que estás equivocado. De la documentación "Quitar elimina del rango [primero, último] todos los elementos que son iguales al valor. Es decir, eliminar devuelve un iterador new_last tal que el rango [first, new_last) no contiene elementos iguales al valor. [1] Los iteradores en el rango [new_last, last] todos siguen siendo referenciables, pero los elementos a los que apuntan no están especificados. Remove es estable, lo que significa que el orden relativo de los elementos que no son iguales al valor no se modifica. " http://www.sgi.com/tech/stl/remove.html – celavek

12

remove_if no coloca los elementos extraídos en ningún lugar; los elementos después del nuevo final tendrán sus valores anteriores, por lo que algunos de los elementos eliminados podrían faltar y algunos de los elementos preservados podrían duplicarse. Esto es más rápido que partition, y se puede hacer con iteradores de reenvío, mientras que partition requiere iteradores bidireccionales.

Actualización: en C++ 0x, partition sólo se requiere hacia adelante iteradores, pero será aún más lento si los iteradores no son bidireccionales.

+0

Si 'partition' requiere iteradores bidireccionales, ¿cómo es que funciona en' forward_list'? – fredoverflow

+0

@FredOverflow: porque C++ 0x cambia el contrato de 'partition' para llevar adelante los iteradores. –

+1

'partition' es mucho más rápido que' remove_if' en algunos casos. Si el elemento que se va a eliminar está al principio de un vector enorme, 'remove_if' moverá todo a la izquierda, mientras que' partition' simplemente cambiará el elemento que se eliminará con el último. – aberaud

4

Si lo entendí bien, remove en realidad no intercambia ningún elemento, simplemente mueve elementos para los cuales el predicado (en el caso de remove_if) es falso al comienzo de la secuencia. Si tiene

a = [1,1,1,2,3]

y llamar remove(a.begin(),a.end(),1), tendrá

a = [2,3,1,2,3]

después. remove devuelve un iterador al tercer elemento en este caso (si no recuerdo mal ...)

partition por otro lado conserva todos los elementos originales de la secuencia, pero cambia su orden de modo que los elementos para los que el predicado determinado es verdadero se colocan delante de los elementos para los que no lo es.

partition(a.begin(), a.end(), not_equal<int>(1)) produce

a = [2,3,1,1,1]

+2

Tenga en cuenta que no se garantiza qué 'std :: remove()' deja atrás _after_ el nuevo iterador final que devuelve. Si bien el resultado que muestra es probable, no está garantizado. – sbi

+0

Pensé que 'std :: remove' tenía la garantía de dejar los elementos detrás del nuevo iterador final sin cambios (también seguirían estando accesibles). Pero el estándar podría haberme equivocado :) ... – MartinStettner

+0

El estándar no especifica qué sucede con los elementos después del final del nuevo rango. Si bien es difícil imaginar que una implementación sensata los afectaría, no hay garantía. –

Cuestiones relacionadas