Dois-je utiliser
std::sort(numbers.begin(), numbers.end(), std::greater<int>());
ou
std::sort(numbers.rbegin(), numbers.rend()); // note: reverse iterators
trier un vecteur par ordre décroissant? Y a-t-il des avantages ou des inconvénients avec l'une ou l'autre approche?
reverse_iterator
.std::sort(b, e);
met le minimum àb
(dans notre casrbegin
, donc le dernier élément) et le maximum àe
(dans notre casrend
, donc le premier élément).Réponses:
En fait, la première est une mauvaise idée. Utilisez soit le second , soit ceci:
De cette façon, votre code ne se cassera pas en silence lorsque quelqu'un décide de
numbers
maintenirlong
oulong long
au lieu deint
.la source
greater
que l'autre?rbegin
etrend
ont été faites dans un but précis.std::greater<typename decltype(numbers)::value_type>()
ou quelque chose?std::greater<>()
depuis C ++ 14.Utilisez le premier:
Il est explicite de ce qui se passe - moins de chance de mal interpréter
rbegin
commebegin
, même avec un commentaire. C'est clair et lisible, c'est exactement ce que vous voulez.De plus, le second peut être moins efficace que le premier étant donné la nature des itérateurs inversés, bien que vous deviez le profiler pour en être sûr.
la source
Avec c ++ 14, vous pouvez faire ceci:
la source
Et ça?
la source
=
et ne+
sont que des commodités signifiant∈
et∪
. Dans ce cas,O(n*log(n)) + O(n)
est une notation pratiqueO(n*log(n)) ∪ O(n)
qui est la même queO(n*log(n))
. Le mot «calcul» est une bonne suggestion et vous avez raison sur le ton.Au lieu d'un foncteur comme Mehrdad l'a proposé, vous pouvez utiliser une fonction Lambda.
la source
Selon ma machine, le tri d'un
long long
vecteur de [1..3000000] à l'aide de la première méthode prend environ 4 secondes, tandis que l'utilisation de la seconde prend environ deux fois plus de temps. Cela dit quelque chose, évidemment, mais je ne comprends pas non plus pourquoi. Pensez simplement que ce serait utile.Même chose rapportée ici .
Comme l'a dit Xeo,
-O3
ils utilisent à peu près le même temps pour terminer.la source
reverse_iterator
opérations qui n'étaient pas intégrées, et étant donné qu'elles ne sont qu'un wrapper autour des itérateurs réels, il n'est pas étonnant qu'elles prennent le double du temps sans s'aligner.base()
fonction membre, par exemple, retourne l'itérateur encapsulé.std::vector<>::reverse_iterator
est mis en œuvre en termes destd::reverse_iterator<>
. Bizarre; aujourd'hui j'ai appris. :-PVous pouvez utiliser la première approche car vous obtenez plus d'efficacité que la seconde.
Complexité temporelle de la première approche inférieure à la seconde.
la source
la source
TL; DR
Utilisez n'importe lequel. Ce sont presque les mêmes.
Réponse ennuyeuse
Comme d'habitude, il y a des avantages et des inconvénients.
Utilisation
std::reverse_iterator
:operator>()
std::greater<int>()
À utiliser
std::greater
lorsque:Quant aux performances, les deux méthodes sont tout aussi efficaces. J'ai essayé le benchmark suivant:
Avec cette ligne de commande:
std::greater
demostd::reverse_iterator
demoLes horaires sont les mêmes. Valgrind signale le même nombre d'échecs de cache.
la source
Je ne pense pas que vous devriez utiliser l'une ou l'autre des méthodes de la question car elles sont toutes deux déroutantes, et la seconde est fragile comme Mehrdad le suggère.
Je recommanderais ce qui suit, car il ressemble à une fonction de bibliothèque standard et rend son intention claire:
la source
std::greater
comparateur ....Vous pouvez soit utiliser le premier ou essayer le code ci-dessous qui est tout aussi efficace
la source