web-dev-qa-db-fra.com

Comparaison entre timsort et quicksort

Pourquoi est-ce que j'entends surtout parler de quicksort comme étant l'algorithme de tri global le plus rapide alors que timsort (selon wikipedia) semble fonctionner beaucoup mieux? Google n'a pas semblé faire de comparaison.

51
chenglou

TimSort est hautement optimisé mergesort, il est stable et plus rapide que l'ancien mergesort.

en comparant avec quicksort, il présente deux avantages:

  1. Il est incroyablement rapide pour une séquence de données presque triée (y compris des données triées en sens inverse);
  2. Le pire des cas reste O (N * LOG (N)).

Pour être honnête, je ne pense pas que le n ° 1 soit un avantage, mais cela m'a impressionné. 

Voici les avantages de QuickSort

  1. QuickSort est très très simple, même une implémentation hautement optimisée, nous pouvons écrire ses codes pseduo en 20 lignes;
  2. QuickSort est le plus rapide dans la plupart des cas;
  3. La consommation de mémoire est LOG (N).

Actuellement, Java 7 SDK implémente timsort et une nouvelle variante de tri rapide: à savoir Dual Pivot QuickSort.

Si vous avez besoin d'un tri stable, essayez timsort, sinon commencez par quicksort.

31
Chang

Plus ou moins, cela tient au fait que Timsort est un algorithme de tri hybride. Cela signifie que bien que les deux tris sous-jacents qu’il utilise (le tri Mergesort et le tri Insertion) soient pires que Quicksort pour de nombreux types de données, Timsort ne les utilise que s’il est avantageux de le faire. 

Sur un niveau légèrement plus profond, comme le dit Patrick87 , le tri rapide est le pire des cas, O (n2) algorithme. Choisir un bon pivot n'est pas difficile , mais garantir un tri rapide O (n log n) se fait au détriment d'un tri généralement plus lent.

Pour plus de détails sur Timsort, voir this answer et l'article de blog lié. Il suppose en principe que la plupart des données sont déjà partiellement triées et construit des "séries" de données triées permettant des fusions efficaces à l'aide de mergesort.

23
brc

En règle générale, le tri rapide est le meilleur algorithme pour un tableau primitif. Cela est dû à la localisation de la mémoire et au cache.

JDK7 utilise le tableau TimSort for Object. Le tableau d'objets ne contient que la référence d'objet. L'objet lui-même est stocké dans Heap. Pour comparer un objet, nous devons lire un objet à partir du tas. Cela revient à lire une partie du tas pour un objet, puis à lire au hasard un objet à partir d’une autre partie du tas. Il y aura beaucoup de cache miss. Je suppose que pour cette raison, la localité de la mémoire n’a plus d’importance. C'est peut-être pour cette raison que JDK utilise uniquement le tableau TimSort for Object s'il s'agit d'un tableau primitif. 

Ceci est seulement ma conjecture.

15
jason zhang

Voici les numéros de référence de ma machine (CPU i7-6700, 3,4 GHz, Ubuntu 16.04, gcc 5.4.0, paramètres: SIZE = 100000 et RUNS = 3):

$ ./demo 
Running tests
stdlib qsort time:                 12246.33 us per iteration
##quick sort time:                  5822.00 us per iteration
merge sort time:                    8244.33 us per iteration
...    
##tim sort time:                    7695.33 us per iteration
in-place merge sort time:           6788.00 us per iteration    
sqrt sort time:                     7289.33 us per iteration    
...
grail sort dyn buffer sort time:    7856.67 us per iteration

La référence provient du projet sort de Swenson dans lequel il a implémenté plusieurs algorithmes de tri dans C. Vraisemblablement, ses implémentations sont suffisamment bonnes pour être représentatives, mais je ne les ai pas encore analysées. 

Donc, vous ne pouvez vraiment pas dire. Les numéros de référence ne restent pertinents que pendant deux ans au maximum, puis vous devez les répéter. Peut-être que timsort a battu qsort waaay en 2011 lorsque la question a été posée, mais les temps ont changé. Ou qsort était toujours le plus rapide, mais timsort le battait sur des données non aléatoires. Ou bien le code de Swenson n’est pas si bon et un meilleur programmeur inverserait la tendance en faveur de timsort. Ou peut-être que je suis nul et que je n'ai pas utilisé la bonne variable CFLAGS lors de la compilation du code. Ou ... tu comprends le point. 

4
Björn Lindqvist

Je ne peux pas utiliser le tri Java standard dans les compétitions de programmation codeforces, car Java utilise un tri rapide sur pivot pour les tableaux entiers et doubles, et il existe donc des tableaux nécessitant un temps d'exécution de O (n ^ 2). Et certaines données de test étant souvent composées avec ces tableaux, le programme prend trop de temps et échoue. Je dois donc passer à mon propre mergeSort à la place. Cela ne peut pas arriver avec l'algorithme timsort. 

0
user3814357