Devo usar
std::sort(numbers.begin(), numbers.end(), std::greater<int>());
ou
std::sort(numbers.rbegin(), numbers.rend()); // note: reverse iterators
classificar um vetor em ordem decrescente? Existem benefícios ou desvantagens em uma abordagem ou outra?
reverse_iterator
as.std::sort(b, e);
coloca o mínimo emb
(no nosso casorbegin
, portanto, o último elemento) e o máximo eme
(no nosso casorend
, o primeiro elemento).Respostas:
Na verdade, o primeiro é uma má ideia. Use o segundo , ou este:
Dessa forma, seu código não será interrompido silenciosamente quando alguém decidir que
numbers
deve aguardarlong
ou emlong long
vez deint
.fonte
greater
que é o outro?rbegin
erend
foram feitos para uma finalidade específica.std::greater<typename decltype(numbers)::value_type>()
ou algo assim?std::greater<>()
desde o C ++ 14.Use o primeiro:
É explícito o que está acontecendo - menos chance de interpretar mal
rbegin
comobegin
, mesmo com um comentário. É claro e legível, exatamente o que você deseja.Além disso, o segundo pode ser menos eficiente que o primeiro, dada a natureza dos iteradores reversos, embora você precise criar um perfil para ter certeza.
fonte
Com o c ++ 14, você pode fazer isso:
fonte
Que tal isso?
fonte
=
e+
são apenas conveniências∈
e significando∪
. Nesse caso,O(n*log(n)) + O(n)
é uma notação conveniente para aO(n*log(n)) ∪ O(n)
qual é o mesmo queO(n*log(n))
. A palavra "computação" é uma boa sugestão e você está certo sobre o tom.Em vez de um functor como Mehrdad propôs, você poderia usar uma função Lambda.
fonte
De acordo com minha máquina, classificar um
long long
vetor de [1..3000000] usando o primeiro método leva cerca de 4 segundos, enquanto o uso do segundo leva cerca de duas vezes o tempo. Isso diz algo, obviamente, mas também não entendo o porquê. Apenas pense que isso seria útil.A mesma coisa relatada aqui .
Como disse Xeo,
-O3
eles usam quase o mesmo tempo para terminar.fonte
reverse_iterator
operações não foram incorporadas e, como são apenas um invólucro dos iteradores reais, não é de admirar que eles demorem o dobro do tempo sem inline.base()
função de membro, por exemplo, retorna o iterador agrupado.std::vector<>::reverse_iterator
seja implementado em termos destd::reverse_iterator<>
. Bizarro; hoje eu aprendi. :-PVocê pode usar a primeira abordagem por obter mais eficiência que a segunda.
A complexidade do tempo da primeira abordagem é menor que a segunda.
fonte
fonte
TL; DR
Use qualquer. Eles são quase os mesmos.
Resposta chata
Como sempre, existem prós e contras.
Use
std::reverse_iterator
:operator>()
std::greater<int>()
Use
std::greater
quando:Quanto ao desempenho, ambos os métodos são igualmente eficientes. Eu tentei o seguinte benchmark:
Com esta linha de comando:
std::greater
demostd::reverse_iterator
demoOs horários são os mesmos. O Valgrind relata o mesmo número de falhas de cache.
fonte
Não acho que você deva usar um dos métodos da pergunta, pois ambos são confusos, e o segundo é frágil, como sugere Mehrdad.
Eu defenderia o seguinte, pois parece uma função de biblioteca padrão e torna clara sua intenção:
fonte
std::greater
comparador ....Você pode usar o primeiro ou tentar o código abaixo, que é igualmente eficiente
fonte