2010-08-19 10 views

Odpowiedz

37

usunąć [...] Umieszcza 'usunięte' elementów na początku sekwencji

Co? Nie. Zarówno remove_if, jak i partition stawiają "dobre" elementy jako pierwsze. partition umieszcza następnie "złe" elementy, natomiast remove_if nie określa, co jest po nim - może to być złe elementy, ale może również być kopią dowolnego (dobrego lub złego) elementu.

Na przykład, jeśli partition 1 2 3 4 5 na nawet, można dostać 2 4 5 3 1 (zauważ, że każdy element występuje dokładnie raz), natomiast jeśli remove_if z nieparzystych elementów, to polubisz zdobądź 2 4 3 4 5 (zauważ duplikaty).

+0

dziękuję, zrozumiałem to –

2

Od C++ Standard Library: A Tutorial i Reference

remove() - usuwa elementy z danej wartości logicznie jedynie poprzez nadpisanie ich z następujących elementów, które nie zostały usunięte. Nie zmieniaj liczby elementów w zakresach, w których działają. Zamiast tego wracają do położenia nowego „koniec” zakresu

partycja() - Zmienia kolejność elementów tak, że elementy spełniające kryterium są na przedniej

stable_partition() - tak samo jak partycja(), ale zachowuje względem kolejności dopasowanie i elementy niepasujących

+0

ładne wyjaśnienie. – Chubsdad

-1

strefy - „grupy” elementy pojemnika według pewnego predykatu (np nieparzyste i parzyste STD :: wektor)

usunąć - usuwa certyfikat wartość ain z pojemnika; w rzeczywistości elementy są przemieszczane do końca pierwotnego pojemnika iterację na nowy koniec jest zwrócony, „usunięty” elementy są jeszcze dostępne

Edycja:

usunięty - usuwa się określoną wartość z pojemnika; elementy NIE są przenoszone na koniec początkowego kontenera, jak podano powyżej, zwracany jest iterator do nowego końca, ale iteratory w zakresie [newEnd, last] są nadal dereferencyjne, a więc dostępne, ALE elementy, na które wskazują, są nieokreślone.

+0

To źle, usuń nadpisuje "usunięte" elementy przez następujące, więc nie wszystkie z nich mogą być dostępne później ... – MartinStettner

+0

Chciałbym wiedzieć, co jest nie tak z moją odpowiedzią, jeśli to możliwe. Może nauczę się czegoś w tym procesie. – celavek

+0

@MartinStettner Myślę, że się mylisz. Z dokumentacji "Remove usuwa z zakresu [pierwszy, ostatni) wszystkie elementy, które są równe wartości. Oznacza to, że remove zwraca iterator new_last tak, że range [first, new_last] nie zawiera elementów równych wartości. [1] Iteratory w zakresie [new_last, last) wszystkie są nadal dereferencyjne, ale elementy, na które wskazują, są nieokreślone. Remove jest stabilny, co oznacza, że ​​względna kolejność elementów, które nie są równe wartości, pozostaje niezmieniona. " http://www.sgi.com/tech/stl/remove.html – celavek

12

nie umieszcza usuniętych elementów w dowolnym miejscu; elementy po nowym końcu będą miały swoje stare wartości, więc niektóre z usuniętych elementów mogą nie być dostępne, a niektóre z zachowanych elementów mogą zostać zduplikowane. Jest to szybsze niż partition i może być wykonane z iteratorami do przodu, podczas gdy partition wymaga dwukierunkowych iteratorów.

Aktualizacja: w C++ 0x, partition wymagać będzie tylko do przodu iteratory, ale będzie jeszcze wolniejszy, jeśli nie są iteratory dwukierunkowe.

+0

Jeśli 'partition' wymaga dwukierunkowych iteratorów, jak to działa na' forward_list'? – fredoverflow

+0

@FredOverflow: ponieważ C++ 0x zmienia umowę 'partition', aby kontynuować iteratory. –

+1

'partition' jest w niektórych przypadkach znacznie szybszy niż' remove_if'. Jeśli element, który ma zostać usunięty, znajduje się na początku dużego wektora, 'remove_if' przeniesie całość w lewo, natomiast' partition' po prostu zamieni element, który ma zostać usunięty, z ostatnim. – aberaud

4

Jeśli dobrze to zrozumiałem, remove w rzeczywistości nie zamienia żadnych elementów, ale po prostu przenosi elementy, dla których predykat (w przypadku remove_if) jest fałszywy na początku sekwencji. Jeśli masz

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

i nazywają remove(a.begin(),a.end(),1), musisz

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

później. remove zwraca iterator do trzeciego elementu w tym przypadku (jeśli dobrze pamiętam ...) Z drugiej strony zachowuje wszystkie oryginalne elementy sekwencji, ale zmienia ich kolejność tak, że elementy, dla których dany predykat jest prawdziwy, są umieszczane przed elementami, dla których nie jest.

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

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

+2

Zauważ, że nie jest gwarantowane, co 'std :: remove()' pozostawia za _ późniejszy iterator końca, który powraca. Chociaż wynik, który pokazujesz, jest prawdopodobny, nie jest gwarantowany. – sbi

+0

Myślałem, że 'std :: remove' gwarantował pozostawienie elementów za iteratorem nowego końca bez zmian (będą one również dostępne). Ale może mnie udowodnić, że nie spełnia normy :) ... – MartinStettner

+0

Standard nie określa, co dzieje się z elementami po końcu nowego zakresu. Choć trudno sobie wyobrazić, że jakakolwiek rozsądna implementacja ich dotknie, nie ma żadnej gwarancji. –

Powiązane problemy