Quel est l'algorithme de tri le plus rapide pour un tableau d'entiers?

55

J'ai rencontré de nombreux algorithmes de tri au cours de mes études secondaires. Cependant, je ne sais jamais lequel est le plus rapide (pour un tableau aléatoire d'entiers). Donc mes questions sont:

  • Quel est l'algorithme de tri le plus rapide actuellement connu?
  • Théoriquement, est-il possible qu'il y en ait des plus rapides? Alors, quelle est la moindre complexité pour le tri?
gen
la source
7
Qu'entendez-vous par "rapide"? Que voulez-vous mesurer?
Raphaël
2
Que signifie "tableau aléatoire de nombres entiers"? Au hasard avec quelle distribution? distribution uniforme? Gaussien? Selon la distribution, il est possible que les algorithmes de temps d'exécution attendus soient meilleurs que . O(nlogn)
Bakuriu
@gen Jetez un coup d'oeil à la sorte Radix. Une implémentation correcte a par exemple une complexité de O (n) pour Int32.
Ce
Jetez un coup d'œil au critère de tri
adrianN
1
@gen: En termes de asymptotics? Ensuite, rien de plus simple: choisissez l’un des algorithmes . Notez que cela n’a peut-être rien à voir avec les performances (moyennes) dans le monde réel. Cela peut être une lecture intéressante à cet égard. & thetav ( n log n )ΘΘ(nlogn)
Raphaël

Réponses:

42

De manière générale, il existe les algorithmes de tri , tels que le tri par insertion, le tri par bulle et le tri par sélection, que vous ne devriez normalement utiliser que dans des circonstances spéciales; Quicksort, qui est le cas le plus défavorable mais assez souvent avec de bonnes constantes et propriétés et qui peut être utilisé comme procédure de tri polyvalente; les algorithmes , tels que merge-sort et heap-sort, qui sont également de bons algorithmes de tri à usage général; et les algorithmes de tri , ou linéaire, pour les listes d'entiers, tels que les tris de base, les tranches et les triages de comptage, qui peuvent convenir en fonction de la nature des entiers dans vos listes.O ( n 2 ) O ( n log n ) O ( n log n ) O ( n )O(n2)O(n2)O(nlogn)O(nlogn)O(n)

Si les éléments de votre liste sont tels que tout ce que vous savez à leur sujet est la relation d'ordre total qui les sépare, les algorithmes de tri optimaux auront alors la complexité . Il s’agit d’un résultat plutôt intéressant, pour lequel vous devriez pouvoir trouver facilement des détails en ligne. Les algorithmes de tri linéaire exploitent des informations supplémentaires sur la structure des éléments à trier, plutôt que la relation d'ordre total entre les éléments.Ω(nlogn)

De manière encore plus générale, l’optimalité d’un algorithme de tri dépend intimement des hypothèses que vous pouvez faire sur le type de listes que vous allez trier (ainsi que sur le modèle de machine sur lequel l’algorithme sera exécuté, ce qui peut entraîner un mauvais tri sinon les algorithmes sont le meilleur choix; envisagez le tri à bulle sur les machines avec une bande pour le stockage). Plus vos hypothèses sont fortes, plus votre algorithme peut couper les angles. Sous des hypothèses très faibles sur l'efficacité avec laquelle vous pouvez déterminer le "tri" d'une liste, la complexité optimale dans le pire des cas peut même être .Ω(n!)

Cette réponse ne traite que des complexités. La durée d'exécution réelle des implémentations d'algorithmes dépendra d'un grand nombre de facteurs qu'il est difficile de prendre en compte dans une réponse unique.

Patrick87
la source
Je suppose que certains de ces devraient être ? ΩOΩ
Raphaël
1
@ Raphaël Meh. Je pense que la plupart d'entre eux sont toute façon. Je suppose que la limite inférieure est probablement mieux rendue . Je vais en changer quelques-unes qui ont le plus de sens. ΩΘΩ
Patrick87
7
Je vote @Raphael obtient un chapeau de police : PΩ
Realz Slaw
2
@ RealzSlaw: Je le porterais fièrement. :]
Raphael
1
@gen Voir stackoverflow.com/a/3274203 pour en savoir plus. Fondamentalement, si les enregistrements individuels sont énormes, et qu'ils ne sont pas stockés de manière aléatoire, et que la quantité de données est telle qu'elle doit être faite sur place, le tri à bulle est la solution. Ces circonstances sont généralement rares de nos jours, mais vous pouvez toujours les rencontrer.
Patrick87
16

La réponse, comme c'est souvent le cas pour de telles questions, est "ça dépend". Cela dépend de facteurs tels que (a) la taille des entiers, (b) si le tableau en entrée contient des entiers dans un ordre aléatoire ou dans un ordre presque trié, (c) si vous avez besoin que l'algorithme de tri soit stable ou non, ainsi que d'autres facteurs, (d) si la liste complète des nombres est ou non mémorisée (tri en mémoire ou tri externe), et (e) la machine sur laquelle vous l'exécutez.

En pratique, l'algorithme de tri de la bibliothèque standard de votre langue sera probablement assez bon (assez proche de l'optimum), si vous avez besoin d'un tri en mémoire. Par conséquent, dans la pratique, utilisez simplement la fonction de tri fournie par la bibliothèque standard et mesurez le temps d'exécution. Ce n'est que si vous constatez que (i) le tri représente une fraction importante du temps total d'exécution et que (ii) le temps d'exécution est inacceptable, si vous vous donnez la peine de jouer avec l'algorithme de tri. Si ces deux conditions sont remplies, vous pouvez alors examiner les aspects spécifiques de votre domaine particulier et expérimenter avec d'autres algorithmes de tri rapide.

Mais de manière réaliste, en pratique, l’algorithme de tri est rarement un goulot d’étranglement majeur en termes de performances.

DW
la source
9

En outre, répondre à votre deuxième question

Théoriquement, est-il possible qu'il y en ait des plus rapides?
Alors, quelle est la moindre complexité pour le tri?

Pour le tri d'usage général, la complexité du problème de tri fondé sur la comparaison est Ω (n log n) . Certains algorithmes effectuent le tri dans O (n), mais ils reposent tous sur des suppositions relatives à l'entrée et ne sont pas des algorithmes de tri à usage général.

Fondamentalement, la complexité est donnée par le nombre minimum de comparaisons nécessaires pour trier le tableau (log n représente la hauteur maximale d'un arbre de décision binaire construit lors de la comparaison de chaque élément du tableau).

Vous pouvez trouver la preuve formelle de la complexité de tri ici :

rla4
la source
3
Cette réponse n'est pas tout à fait correcte. n'est pas une limite inférieure universelle pour le tri. Cette limite inférieure ne s'applique qu'aux tris basés sur la comparaison , c'est-à-dire aux algorithmes de tri qui utilisent uniquement des comparaisons. Certains algorithmes de tri ne sont pas basés sur la comparaison. La déclaration "Certains algorithmes effectuent le tri dans O (n), mais ils reposent tous sur des suppositions relatives à l'entrée et ne sont pas des algorithmes de tri à usage général". pourrait être un peu trompeur - soyez prudent. Radix-sort est un algorithme de tri polyvalent (en supposant que vous triiez des entiers de largeur fixe). Ω(nlogn)
DW
Cela dépend de ce que vous entendez par problème de tri . Les types de comparaison basés sur des objectifs généraux ne sont pas le seul type de problèmes de tri rencontrés par les gens.
Patrick87
1
C'est vrai, bien sûr. J'aurais dû être plus précis, merci de l'avoir signalé. Cependant, j'étais un peu curieux de savoir à quelles autres méthodes de tri (non fondées sur la comparaison) vous vous référiez; Radix Sort est exactement le type d’algorithme O (n) dont je parlais - vous devez supposer quelque chose à propos de l’entrée (entiers à largeur fixe). En ce sens, ce n'est pas un algorithme de tri à usage général, non?
Rla4
1
@DW: Le tri de base ne doit pas être considéré comme un algorithme de tri «généraliste», car il nécessite des clés entières de longueur fixe. n'est-ce pas utile autrement? Mais je comprends ton point. :) Je suppose que mon erreur était de trier tout ce qui pouvait être comparé, plutôt que de trier des nombres entiers , en particulier. Ce sont des problèmes différents et un ensemble différent de solutions possibles. La question mentionne bien "un tableau aléatoire d'entiers", mais j'avoue que je l'ai pris comme exemple, plutôt que comme une restriction.
Rla4
2
@DavidRicherby, après un an et demi, je suis d'accord avec vous. Je vous remercie.
DW
3

L'algorithme de tri le plus rapide en termes de pire cas que j'ai rencontré est celui d' Andersson et al. Il a le pire cas de , ce qui est bien sûr plus rapide que O ( n log n ) .O(nloglogn)O(nlogn)

utilisateur39994
la source
2
C'est très intéressant, mais vous devez donner plus d'informations. Puisque vous mentionnez , je suppose que vous êtes conscient du fait que le tri basé sur la comparaison d’entiers généraux nécessite de manière vérifiable le temps Ω ( n log n ) . Tout ce qui est asymptotiquement plus rapide que cela doit faire des hypothèses sur les données: par exemple, le tri de base s'exécute en temps linéaire en supposant que chaque élément du tableau est au plus constant. Dans quelles conditions cet algorithme est-il trié dans O ( n log log n ) et comment fonctionne-t-il en pratique par rapport à d'autres algorithmes tels que le tri rapide et le tri à base radicale? nlognΩ(nlogn)O(nloglogn)
David Richerby le
1

J'ai lu les deux autres réponses au moment d'écrire ces lignes et je ne pensais pas que ni l'une ni l'autre de vos réponses ne répondent à votre question de manière appropriée. D'autres réponses ont porté sur des idées superflues sur les distributions aléatoires et la complexité de l'espace, qui sont probablement hors de portée des études secondaires. Alors voici ma prise.

Etant donné un tableau avec n éléments entiers, vous avez besoin d’exactement ( n - 1 ) comparaisons entre les éléments pour vérifier si A est trié (commencez simplement au début du tableau et vérifiez l’élément suivant par rapport au dernier élément). En fait, les comparaisons ( n - 1 ) constituent le temps d'exécution optimal pour tout algorithme de tri . En d'autres termes, la limite inférieure du temps d'exécution pour tout algorithme de tri est Ω ( n ) . Si vous vous rappelez un type de base ou un type de seau, vous remarquerez que leurs temps d'exécution sont O ( nAn(n1)A(n1)Ω(n) . Puisque tous les algorithmes de tri sont liés ci-dessous par Ω ( n ) , je dirais que le tri de base et le tri de compartiment sont les algorithmes les plus rapides pour trier un tableau d'entiers.O(n)Ω(n)

De plus, si vous n'êtes pas familier avec ce que ou O ( n ) : Les deux notations signifient que l'algorithme nécessite environ n opérations à compléter (peut être 2 n ou 3 n - 5 , mais pas 1 ou n 2 opérations) .Ω(n)O(n)n2n3n-51n2

bourbaki4481472
la source
O(n)nlgnn232O(n)O(nlgn)(pour quicksort ou mergesort), dans la pratique, la comparaison n’est pas aussi claire: les constantes cachées dans la notation big-O deviennent très importantes et la constante pour radix-sort est supérieure à la constante pour quicksort ou mergesort.
DW
lg(n)n
Ω(n)
2
O(wn)www{0,,2w1}lognnw=bûchennbûchen.
David Richerby
1

O(nloglogn)
O(nloglogU)U
l'idiot
la source
0

bûche(n!)

Ω(n)

Yves Daoust
la source
0

Comme vous ne mentionnez aucune restriction sur le matériel et que vous recherchez "le plus rapide", je vous conseillerais de choisir l'un des algorithmes de tri en parallèle en fonction du matériel disponible et du type de saisie dont vous disposez.

En théorie, par exemple quick_sortest O(n log n). Avec les pprocesseurs, idéalement, cela devrait se résumer O(n/p log n)si nous le faisons en parallèle.

Pour citer Wikipedia: la complexité temporelle de ...

Le tri parallèle optimal est O (log n)

En pratique, il serait impossible de réaliser des tailles d’entrée massives en O(log n)raison de problèmes d’évolutivité.

Voici le pseudo-code pour le tri par fusion parallèle . L'implémentation de merge()peut être la même que dans le type de fusion normal:

// Sort elements lo through hi (exclusive) of array A.
algorithm mergesort(A, lo, hi) is
    if lo+1 < hi then  // Two or more elements.
        mid = ⌊(lo + hi) / 2⌋
        fork mergesort(A, lo, mid)
        mergesort(A, mid, hi)
        join
        merge(A, lo, mid, hi)

Regarde aussi:

Kashyap
la source
O(n2)
@Evil Oui. Quicksort n'est pas bien adapté au traitement en parallèle. C'est un exemple. Ceux qui devraient être utilisés sont listés dans les liens donnés.
Kashyap