Powinienem użyć
std::sort(numbers.begin(), numbers.end(), std::greater<int>());
lub
std::sort(numbers.rbegin(), numbers.rend()); // note: reverse iterators
posortować wektor w kolejności malejącej? Czy są jakieś zalety lub wady jednego lub drugiego podejścia?
reverse_iterator
.std::sort(b, e);
stawia minimum nab
(w naszym przypadkurbegin
, więc ostatni element) i maksimum nae
(w naszym przypadkurend
, więc pierwszy element).Odpowiedzi:
Właściwie pierwszy to zły pomysł. Użyj albo drugiego , albo tego:
W ten sposób Twój kod nie zostanie po cichu zerwany, gdy ktoś zdecyduje się
numbers
wstrzymaćlong
lublong long
zamiast niegoint
.źródło
greater
inne?rbegin
irend
zostały wykonane w określonym celu.std::greater<typename decltype(numbers)::value_type>()
czy coś?std::greater<>()
od C ++ 14.Użyj pierwszego:
To jawne, co się dzieje - mniejsze prawdopodobieństwo błędnej
rbegin
jakbegin
, nawet z komentarzem. Jest jasny i czytelny, a dokładnie tego chcesz.Ponadto drugi może być mniej wydajny niż pierwszy, biorąc pod uwagę naturę iteratorów odwrotnych, chociaż trzeba by go profilować, aby mieć pewność.
źródło
W c ++ 14 możesz to zrobić:
źródło
A co z tym?
źródło
=
i+
oznacza tylko wygody oznaczające∈
i∪
. W takim przypadkuO(n*log(n)) + O(n)
jest to wygodny zapis, dlaO(n*log(n)) ∪ O(n)
którego jest taki sam jakO(n*log(n))
. Słowo „obliczenie” jest dobrą sugestią i masz rację co do tonu.Zamiast funktora, jak zaproponował Mehrdad, można użyć funkcji Lambda.
źródło
Według mojej maszyny sortowanie
long long
wektora [1..3000000] przy użyciu pierwszej metody zajmuje około 4 sekund, podczas gdy użycie drugiej zajmuje około dwa razy więcej czasu. To oczywiście coś mówi, ale ja też nie rozumiem, dlaczego. Pomyśl tylko, że byłoby to pomocne.To samo zgłoszono tutaj .
Jak powiedział Xeo,
-O3
wykorzystują mniej więcej tyle samo czasu na zakończenie.źródło
reverse_iterator
operacje nie zostały wprowadzone, a biorąc pod uwagę, że są one tylko otokami rzeczywistych iteratorów, nic dziwnego, że zajmują dwa razy więcej czasu bez wprowadzania.base()
przykład funkcja członka zwraca zawinięty iterator.std::vector<>::reverse_iterator
jest wdrażana pod względemstd::reverse_iterator<>
. Dziwaczny; Dzisiaj się uczę. :-PMożesz zastosować pierwsze podejście ze względu na większą wydajność niż drugie.
Złożoność czasowa pierwszego podejścia mniejsza niż druga.
źródło
źródło
TL; DR
Użyj dowolnego. Są prawie takie same.
Nudna odpowiedź
Jak zwykle są plusy i minusy.
Użyj
std::reverse_iterator
:operator>()
std::greater<int>()
Użyj,
std::greater
gdy:Jeśli chodzi o wydajność, obie metody są równie wydajne. Próbowałem następującego testu porównawczego:
Za pomocą tego wiersza poleceń:
std::greater
demostd::reverse_iterator
demoCzasy są takie same. Valgrind zgłasza taką samą liczbę braków pamięci podręcznej.
źródło
Nie sądzę, że powinieneś użyć jednej z metod w pytaniu, ponieważ obie są mylące, a druga jest krucha, jak sugeruje Mehrdad.
Zalecałbym następujące, ponieważ wygląda ona jak standardowa funkcja biblioteki i wyraźnie wyjaśnia jej intencję:
źródło
std::greater
komparatora ...Możesz użyć pierwszego lub wypróbować poniższy kod, który jest równie wydajny
źródło