Comme Merge Sort, QuickSort est un algorithme Divide and Conquer. Il sélectionne un élément comme pivot et partitionne le tableau donné autour du pivot sélectionné. Il existe de nombreuses versions de quickSort qui sélectionnent le pivot de différentes manières.
- Choisissez toujours le premier élément comme pivot.
- Choisissez toujours le dernier élément comme pivot (implémenté ci-dessous)
- Choisissez un élément aléatoire comme pivot.
- Choisissez la médiane comme pivot.
Le processus clé dans quickSort est partition (). La cible des partitions est, étant donné un tableau et un élément x du tableau comme pivot, mettre x à sa position correcte dans un tableau trié et mettre tous les éléments plus petits (plus petits que x) avant x, et mettre tous les éléments plus grands (plus grands que x) après X. Tout cela doit être fait en temps linéaire.
Pseudo-code pour la fonction QuickSort récursive:
Algorithme de partition
Il peut y avoir plusieurs façons de faire la partition, le pseudo-code suivant adopte la méthode donnée dans le livre CLRS. La logique est simple, nous partons de lélément le plus à gauche et gardons une trace de lindex des éléments plus petits (ou égaux à) comme i. En parcourant, si nous trouvons un élément plus petit, nous échangeons lélément courant avec arr. Sinon, nous ignorons lélément courant.
Pseudo-code pour la partition ()
Illustration de la partition ():
Implémentation:
Voici les implémentations de QuickSort:
Sortie:
Sorted array:1 5 7 8 9 10
Analyse de QuickSort
Le temps pris par QuickSort en général peut sécrire comme suit.
T(n) = T(k) + T(n-k-1) + (n)
Les deux premiers termes sont pour deux appels récursifs, le dernier terme est pour le processus de partition. k est le nombre déléments plus petits que pivot.
Le temps pris par QuickSort dépend du tableau dentrée et de la stratégie de partition. Voici trois cas.
Pire cas: Le pire des cas se produit lorsque le processus de partition choisit toujours le plus grand ou le plus petit élément comme pivot. Si nous considérons la stratégie de partition ci-dessus où le dernier élément est toujours choisi comme pivot, le pire des cas se produirait lorsque le tableau est déjà trié par ordre croissant ou décroissant. Voici la récidive pour le pire des cas.
T(n) = T(0) + T(n-1) + (n)which is equivalent to T(n) = T(n-1) + (n)
La solution de la récurrence ci-dessus est (n2).
Meilleur cas: Le meilleur des cas se produit lorsque le processus de partition sélectionne toujours le élément central comme pivot. Voici la récurrence pour le meilleur des cas.
T(n) = 2T(n/2) + (n)
La solution de la récurrence ci-dessus est (nLogn). Il peut être résolu en utilisant le cas 2 du théorème maître.
Cas moyen:
Pour faire une analyse de cas moyenne, nous devons considérer toutes les permutations possibles du tableau et calculer le temps pris par chaque permutation qui ne le fait pas semble facile.
Nous pouvons avoir une idée du cas moyen en considérant le cas où la partition met O (n / 9) éléments dans un ensemble et O (9n / 10) éléments dans un autre ensemble. Voici la récurrence de ce cas.
T(n) = T(n/9) + T(9n/10) + (n)
La solution de la récurrence ci-dessus est également O (nLogn)
Bien que la complexité temporelle du pire des cas de QuickSort soit O (n2) qui est plus que de nombreux autres algorithmes de tri comme le tri par fusion et le tri par tas, QuickSort est plus rapide en pratique, car sa boucle interne peut être efficacement implémentée sur la plupart des architectures et dans la plupart des données du monde réel. QuickSort peut être implémenté de différentes manières en modifiant le choix du pivot, de sorte que le pire des cas se produise rarement pour un type de données donné. Cependant, le tri par fusion est généralement considéré comme meilleur lorsque les données sont énormes et stockées dans un stockage externe.
QuickSort est-il stable?
Limplémentation par défaut nest pas stable. Cependant, nimporte quel algorithme de tri peut être rendu stable en considérant les index comme paramètre de comparaison.
QuickSort est-il en place?
Selon la définition large de lalgorithme sur place, il est considéré comme un algorithme de tri sur place car il utilise des espace uniquement pour stocker les appels de fonction récursifs mais pas pour manipuler lentrée.
Comment implémenter QuickSort pour les listes liées?
QuickSort sur une seule liste liée
QuickSort sur une liste doublement liée
Pouvons-nous implémenter QuickSort de manière itérative?
Oui, veuillez vous référer au tri rapide itératif.
Pourquoi le tri rapide est préférable à MergeSort pour trier les tableaux
Le tri rapide dans sa forme générale est un tri sur place (cest-à-dire quil ne nécessite aucun stockage supplémentaire) alors que le tri par fusion nécessite un stockage supplémentaire O (N), N désignant la taille du tableau qui peut être assez chère. Lallocation et la désallocation de lespace supplémentaire utilisé pour le tri par fusion augmente la durée dexécution de lalgorithme. En comparant la complexité moyenne, nous constatons que les deux types de tris ont une complexité moyenne O (NlogN) mais les constantes diffèrent. Pour les tableaux, le tri par fusion perd en raison de lutilisation dun espace de stockage O (N) supplémentaire.
La plupart des implémentations pratiques du tri rapide utilisent une version aléatoire. La version aléatoire a prévu une complexité temporelle de O (nLogn).Le pire des cas est également possible dans la version aléatoire, mais le pire des cas ne se produit pas pour un modèle particulier (comme un tableau trié) et le tri rapide aléatoire fonctionne bien en pratique.
Le tri rapide est également un tri convivial pour le cache algorithme car il a une bonne localisation de référence lorsquil est utilisé pour les tableaux.
Le tri rapide est également récursif de queue, donc les optimisations des appels de queue sont effectuées.
Pourquoi MergeSort est préférable à QuickSort pour les listes liées ?
Dans le cas des listes liées, le cas est différent principalement en raison de la différence dallocation de mémoire entre les tableaux et les listes liées. Contrairement aux tableaux, les nœuds de liste liée peuvent ne pas être adjacents en mémoire. Contrairement au tableau, dans la liste chaînée, nous pouvons insérer des éléments au milieu dans un espace supplémentaire O (1) et un temps O (1). Par conséquent, lopération de fusion du tri par fusion peut être implémentée sans espace supplémentaire pour les listes liées.
Dans les tableaux, nous pouvons faire un accès aléatoire car les éléments sont continus en mémoire. Disons que nous avons un tableau dentiers (4 octets) A et que ladresse de A soit x puis pour accéder à A, nous pouvons accéder directement à la mémoire en (x + i * 4). Contrairement aux tableaux, nous ne pouvons pas faire daccès aléatoire en liste chaînée. Le tri rapide nécessite beaucoup de ce type daccès. Dans la liste chaînée pour accéder au i’e index, nous devons parcourir chaque nœud de la tête au i’e nœud car nous n’avons pas de bloc de mémoire continu. Par conséquent, les frais généraux augmentent pour un tri rapide. Le tri par fusion accède aux données de manière séquentielle et le besoin daccès aléatoire est faible.
Comment optimiser QuickSort pour quil prenne O (Log n) despace supplémentaire dans le pire des cas?
Veuillez consulter QuickSort Tail Call Optimization (Réduire lespace du pire des cas pour Log n)
Instantanés:
- Quiz sur QuickSort
- Articles récents sur QuickSort
- Pratique de codage pour tri.
Autres algorithmes de tri sur GeeksforGeeks / GeeksQuiz:
Tri par sélection, Tri par bulles, Tri par insertion, Tri par fusion, Tri par tas, Tri rapide , Tri Radix, Tri par comptage, Tri par seau, Tri Shell, Tri par peigne, Tri par casier