web-dev-qa-db-fra.com

Pourquoi quicksort est plus populaire que radix-sort?

Pourquoi le tri rapide (ou introsort) ou tout autre algorithme de tri basé sur la comparaison est-il plus courant que le tri par radix? Surtout pour le tri des numéros.

Radix-sort n’est pas basé sur la comparaison et peut donc être plus rapide que O (n logn). En fait, il s’agit de O (k n), où k est le nombre de bits utilisés pour représenter chaque élément. Et la surcharge de mémoire n'est pas critique, car vous pouvez choisir le nombre de compartiments à utiliser et la mémoire requise peut être inférieure aux exigences de mergesort.

Est-ce que cela a à voir avec la mise en cache? Ou peut-être accéder à des octets aléatoires d'entiers dans le tableau?

37
Daniyar

Deux arguments me viennent à l’esprit:

  1. Quicksort/Introsort est plus flexible: 

    Quicksort et Introsort fonctionnent bien avec toutes sortes de données. Tout ce dont vous avez besoin pour le tri est la possibilité de comparer les articles. C'est trivial avec des nombres mais vous pouvez aussi trier d'autres données.

    Par contre, la sorte Radix trie les choses uniquement par leur représentation binaire. Il ne compare jamais les éléments les uns contre les autres. 

  2. Le type Radix nécessite plus de mémoire.

    Toutes les implémentations de tri de base que j'ai vues utilisent un tampon secondaire pour stocker les résultats de tri partiels. Cela augmente les besoins en mémoire de l'algorithme de tri. Ce n'est peut-être pas un problème si vous ne triez que quelques kilo-octets, mais si vous entrez dans la plage des gigaoctets, cela fait une énorme différence.

    Si je me souviens bien, il existe un algorithme de tri à base radix sur place.

22
Nils Pipenbrinck

Une réponse évidente est que vous pouvez trier des types arbitraires à l'aide de quicksort (tout ce qui est comparable), alors que vous êtes limité aux nombres avec radix. Et le tri rapide d'IMO est beaucoup plus intuitif.

11
NullUserException

Le tri de base est plus lent pour la plupart des cas d'utilisation réels.

Une des raisons est la complexité de l'algorithme:

Si les éléments sont uniques, k> = log (n). Même avec des éléments en double, l'ensemble des problèmes où k <log (n) est petit.

Une autre est la mise en œuvre:

L'exigence de mémoire supplémentaire (qui en soi est un inconvénient), affecte négativement les performances du cache.

Je pense qu'il est prudent de dire que de nombreuses bibliothèques, comme la bibliothèque standard, utilisent Quicksort car ses performances sont meilleures dans la majorité des cas. Je ne pense pas que la "mise en œuvre difficile" ou le "moins intuitif" soient des facteurs majeurs.

5
Plow

Comme mentionné sur Wikipedia

Le sujet de l'efficacité du tri de base par rapport à d'autres algorithmes de tri est quelque peu délicat et sujet à beaucoup de malentendus. Que le tri de base soit aussi efficace, moins efficace ou plus efficace que les meilleurs algorithmes basés sur la comparaison dépend des détails des hypothèses retenues. L'efficacité du tri de base est O (d · n) pour n touches dont le nombre de chiffres est inférieur ou égal à d. Parfois, d est présenté comme une constante, ce qui rendrait le tri de base meilleur (pour un n suffisamment grand) que les meilleurs algorithmes de tri fondés sur la comparaison, qui sont tous O (n · log (n)) nombre de comparaisons nécessaires. Cependant, d ne peut généralement pas être considéré comme une constante. En particulier, sous l'hypothèse commune (mais parfois implicite) que toutes les clés sont distinctes, alors d doit être au moins de l'ordre de log (n), ce qui donne au mieux (avec des clés compactes) une complexité temporelle O (n · log (n)) . Cela semblerait rendre le tri de base au moins aussi efficace que les meilleurs tris basés sur la comparaison (et pire si les clés sont beaucoup plus longues que log (n)).

L'argument counter est que les algorithmes de comparaison sont mesurés en nombre de comparaisons et non en complexité temporelle réelle. Dans certaines hypothèses, les comparaisons seront en moyenne constantes, dans d'autres non. Les comparaisons de clés générées aléatoirement prennent en moyenne un temps constant, car les clés diffèrent sur le tout premier bit dans la moitié des cas, et sur le second bit sur la moitié de la moitié restante, et ainsi de suite, ce qui donne une moyenne de deux bits besoin d'être comparé. Dans un algorithme de tri, les premières comparaisons effectuées satisfont à la condition d’aléatoire, mais à mesure que le tri progresse, les clés comparées ne sont clairement plus choisies au hasard. Par exemple, considérons un tri par fusion ascendante. La première passe compare des paires de clés aléatoires, mais la dernière passe compare des clés très proches dans l'ordre de tri.

Le facteur décisif est la manière dont les clés sont distribuées. Le meilleur cas pour le tri de base est qu'ils sont pris comme des modèles de bits consécutifs. Cela rendra les touches aussi courtes que possible, en supposant qu'elles soient distinctes. Cela fait un tri de base O (n · log (n)), mais les tris basés sur la comparaison ne seront pas aussi efficaces, car les comparaisons ne seront pas constantes dans le temps sous cette hypothèse. Si nous supposons plutôt que les clés sont des motifs binaires de longueur k · log (n) pour une constante k> 1 et log 2, et qu'elles sont uniformément aléatoires, le tri de la base sera toujours O (n · log (n) ), mais il en va de même pour les tris basés sur la comparaison, car la longueur "extra" fait que même les clés qui sont consécutives dans le résultat trié diffèrent suffisamment pour que les comparaisons soient en moyenne constantes. Si les clés sont plus longues que O (log (n)), mais aléatoires, le tri de base sera inférieur. Il existe de nombreuses autres hypothèses qui peuvent également être formulées, et la plupart nécessitent une étude minutieuse pour permettre une comparaison correcte.

4
Abhinav Chauhan

Les points soulevés dans d'autres réponses sont valables, mais dans la mesure où votre préoccupation est mentionnée dans plusieurs commentaires.

... le fait que les algorithmes de tri par défaut pour les nombres sont implémentés à l'aide de quicksort. Surtout les implémentations dans les librairies ...

Quicksort est le choix "sûr". Le temps d'exécution potentiel d'un type de base basé sur un type de comptage est très attrayant, mais le type de base est susceptible de mal fonctionner sur des ensembles de données malveillants/malheureux. Si le nombre de chiffres des clés en cours de tri s'approche du nombre de clés en cours de tri, le tri de base est effectué sur n ^ 2 avec une complexité d'espace non négligeable, et il a tendance à avoir des constantes d'exécution internes assez élevées autres que celle du nombre des chiffres des clés en cours de tri.
Mergesort est attrayant parce que son comportement est, d’une certaine manière, analogue à un tri rapide qui choisit un pivot optimal à chaque occasion (la médiane). Cependant, il vient avec une complexité d'espace appréciable. Il n’est pas aussi sensible aux données malveillantes/malheureuses que la base, mais n’offre pas non plus le temps d’exécution attrayant possible. Un tri rapide se comporte très bien sur la plupart des jeux de données, à l’exception de ceux triés presque (ou complètement), et est livré avec un minuscule complexité spatiale.
Il est facile de gérer la vulnérabilité de Quicksort en la convertissant en tri rapide aléatoire. La vulnérabilité de Radix sort est résolue en imposant des restrictions sur les clés en cours de tri, ce qui limiterait de manière inhérente les utilisateurs de la bibliothèque. Quicksort est plus performant que la fusion sur de petits ensembles de données et fonctionne raisonnablement lorsque la fusion peut être plus rapide.
Lorsque vous implémentez une bibliothèque, vous souhaitez la rendre génériquement utile. Prenons ces exemples, une application Web et un petit appareil doté d’un microcontrôleur extrêmement restreint. Les applications Web doivent traiter régulièrement des données malveillantes et répondre à une grande variété de besoins. Une bibliothèque avec des restrictions préconditionnées a moins de chance d’être utile. Dans le cas du microcontrôleur, il peut être limité de façon restrictive en termes d'espace et incapable de renoncer au moindre bit où il est possible de le sauvegarder. Quicksort économise de l'espace et ne se termine que plus lentement avec un multiplicateur constant SI une situation survient.
En somme -
1.) Les bibliothèques sont souvent codées pour une utilisation aussi générique que possible
2.) Une bonne performance globale est acceptable, surtout si c’est dans de nombreux cas la meilleure performance
3.) L'espace n'est pas toujours une question primordiale, mais lorsqu'il l'est, il est souvent explicitement restrictif. 

0
Culex