410 votes

Trier un vecteur dans l'ordre décroissant

Dois-je utiliser

std::sort(numbers.begin(), numbers.end(), std::greater<int>());

o

std::sort(numbers.rbegin(), numbers.rend());   // note: reverse iterators

pour trier un vecteur dans l'ordre décroissant ? Y a-t-il des avantages ou des inconvénients à l'une ou l'autre de ces approches ?

4 votes

+1 Je pense que la réponse est évidente, mais cette question comporte une partie intéressante de trivium :)

5 votes

Je voterais pour la première option, juste parce qu'ainsi je n'aurais jamais à faire face à reverse_iterator 's.

4 votes

@wilhelmtell Une question de débutant mais pourquoi le deuxième trierait-il par ordre décroissant ? Nous donnons le même tableau comme entrée à la méthode de tri. C'est juste que nous le donnons dans l'ordre inverse, alors pourquoi devrait-il être trié par ordre décroissant et non croissant comme ce serait le cas avec ar.begin() et ar.end.

157voto

mrexciting Points 851

Avec c++14, vous pouvez le faire :

std::sort(numbers.begin(), numbers.end(), std::greater<>());

21 votes

C++17 std::sort(numbers.begin(), numbers.end(), std::greater{}); C++20 std::ranges::sort(numbers, std::ranges::greater());

143voto

Mehrdad Points 70493

En fait, la première est une mauvaise idée. Utilisez soit le le deuxième ou ceci :

struct greater
{
    template<class T>
    bool operator()(T const &a, T const &b) const { return a > b; }
};

std::sort(numbers.begin(), numbers.end(), greater());

De cette façon, votre code ne se brisera pas silencieusement lorsque quelqu'un décidera de numbers devrait tenir long ou long long au lieu de int .

2 votes

@FredOverflow : Tu as fait les honneurs de ton commentaire ;)

4 votes

Ou restez-en à la première. Utilisez un typedef pour le numberContainer - une bonne idée pour que quelqu'un puisse passer à long long - et écrivez : std::sort(numbers.begin(), numbers.end(), std::greater<numContainer::value_type>()) ;

0 votes

Pourquoi est-il impossible de le faire avec lambda ?

87voto

Xeo Points 69818

Si rien d'autre, la première version est beaucoup plus clair sur votre intention. En fait, j'ai dû vérifier moi-même que la deuxième version trie vraiment dans l'ordre inverse...

83voto

Pubby Points 29386

Utilisez le premier :

std::sort(numbers.begin(), numbers.end(), std::greater<int>());

Il est explicite de ce qui se passe - moins de risque de mauvaise lecture. rbegin comme begin même avec un commentaire. C'est clair et lisible, ce qui est exactement ce que vous voulez.

En outre, la seconde peut être moins efficace que la première, compte tenu de la nature des itérateurs inversés, mais il faudrait en établir le profil pour en être sûr.

35voto

shoumikhin Points 343

Et ça ?

std::sort(numbers.begin(), numbers.end());
std::reverse(numbers.begin(), numbers.end());

15 votes

Une raison pourrait être d'éviter la complexité supplémentaire : O(n * log(n)) + O(n) vs O(n * log(n))

42 votes

@greg O(n * log(n)) = O(n * log(n) + n). Ce sont deux façons de définir le même ensemble. Vous voulez dire "Cela pourrait être plus lent".

6 votes

@pjvandehaar Greg est bien. Il n'a pas explicitement dit, O(n * log(n) + n), il a dit O(n * log(n)) + O(n). Vous avez raison de dire que sa formulation n'est pas claire (en particulier son utilisation abusive du mot complexité), mais vous auriez pu répondre d'une manière plus aimable. Par exemple : Peut-être que vous vouliez utiliser le mot "calcul" au lieu du mot "complexité". Inverser les nombres est une étape O(n) inutile à une étape O(n * log(n)) par ailleurs identique.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X