web-dev-qa-db-fra.com

Pourquoi le tri par insertion est-il préférable au tri rapide pour une petite liste d'éléments?

Le type d'insertion n'est-il pas O (n ^ 2)> Quicksort O (nlogn) ... donc pour un petit n, la relation ne sera-t-elle pas la même?

22
user1031752

La notation Big-O décrit le comportement limitant lorsque n est grand, également appelé comportement asymptotique. Ceci est une approximation. (Voir http://en.wikipedia.org/wiki/Big_O_notation )

Le tri par insertion est plus rapide pour les petits n, car le tri rapide entraîne une surcharge des appels de fonction récursifs. Le tri par insertion est également plus stable que le tri rapide et nécessite moins de mémoire.

Cette question décrit certains avantages supplémentaires du tri par insertion. ( Existe-t-il une bonne raison d'utiliser le tri par insertion? )

20
Casey Robinson

Définir "petit".

Lors de l'analyse comparative des algorithmes de tri, j'ai découvert que passer du tri rapide au tri par insertion, malgré ce que tout le monde disait, nuisait à la performance (tri rapide récursif en C) pour les tableaux de plus de 4 éléments. Et ces tableaux peuvent être triés avec un algorithme de tri optimal dépendant de la taille.

Cela dit, gardez toujours à l'esprit que O(n...) est uniquement le nombre de comparaisons (dans ce cas particulier), pas la vitesse de l'algorithme. La vitesse dépend de la mise en œuvre, e. g., si votre tri rapide fonctionne comme ou non récursif et à quelle vitesse les appels de fonction sont traités.

Dernier point mais non le moindre, la grande notation oh n'est qu'une limite supérieure.

Si l'algorithme A nécessite des comparaisons 10000 n log n et que l'algorithme B nécessite 10 n ^ 2, le premier est O(n log n) et le second est O(n ^ 2). Néanmoins, le second sera (probablement) plus rapide.

10
Dennis

La notation O () est généralement utilisée pour caractériser les performances de gros problèmes, tout en ignorant délibérément des facteurs constants et des corrections additives aux performances.

Cela est important car les facteurs et le temps système peuvent varier considérablement selon les processeurs et les implémentations: les performances obtenues pour un programme de base à un seul thread sur une machine 6502 seront très différentes du même algorithme implémenté comme un programme C exécuté sur un processeur Intel i7. processeur de classe. Notez que l’optimisation de la mise en œuvre est également un facteur: l’attention portée aux détails peut souvent vous permettre d’améliorer considérablement vos performances, même si tous les autres facteurs sont identiques!

Cependant, le facteur constant et les frais généraux sont toujours importants. Si votre application garantit que N ne devient jamais très grand, le comportement asymptotique de O (N ^ 2) par rapport à O (N log N) n'entre pas en jeu.

Le tri par insertion est simple et, pour les petites listes, il est généralement plus rapide qu'un tri rapide ou une fusion similaire. C’est pourquoi une implémentation de type pratique aura généralement recours à un type de tri par insertion pour le "cas de base", au lieu d’être récursive jusqu’à éléments simples.

4
comingstorm

C'est une question de constantes liées au temps d'exécution que nous ignorons dans la notation big-oh (parce que nous sommes concernés par l'ordre de croissance). Pour le tri par insertion, le temps d'exécution est O (n ^ 2), c'est-à-dire que T (n) <= c (n ^ 2), tandis que pour Quicksort, il s'agit de T (n) <= k (nlgn). Comme c est assez petit, pour n petit, le temps d’exécution du tri par insertion est inférieur à celui de Quicksort .....

J'espère que ça aide...

3
bhuwansahni

Le bon exemple concret dans lequel le tri par insertion peut être utilisé conjointement avec quicksort est l'implémentation de la fonction qsort à partir de glibc.

La première chose à souligner est que qsort implémente l'algorithme quicksort avec une pile, car il consomme moins de mémoire, cette pile étant implémentée au moyen de directives de macros.

Résumé de l’implémentation en cours à partir du code source (vous y trouverez de nombreuses informations utiles sous forme de commentaires):

  1. Non récursif

  2. Choisissez l'élément pivot en utilisant un arbre de décision médian de trois

  3. Seuls les partitions rapides TOTAL_ELEMS/MAX_THRESH, en laissant insertion sort afin de classer les éléments MAX_THRESH dans chaque partition . C'est une grosse victoire, car le tri par insertion est plus rapide pour les plus petits, principalement segments de tableau triés.

  4. La plus grande des deux sous-partitions est toujours poussée sur la empiler en premier

Que signifie MAX_THRESH? Eh bien, juste une petite valeur magique constante qui

a été choisi pour fonctionner au mieux sur un Sun 4/260.

0
FUNNYDMAN

Qu'en est-il du tri par insertion binaire? Vous pouvez absolument rechercher la position à permuter en utilisant la recherche binaire.

0
nhp