Il existe deux méthodes de partition quicksort mentionnées dans Cormen:
Hoare-Partition(A, p, r)
x = A[p]
i = p - 1
j = r + 1
while true
repeat
j = j - 1
until A[j] <= x
repeat
i = i + 1
until A[i] >= x
if i < j
swap( A[i], A[j] )
else
return j
et:
Lomuto-Partition(A, p, r)
x = A[r]
i = p - 1
for j = p to r - 1
if A[j] <= x
i = i + 1
swap( A[i], A[j] )
swap( A[i +1], A[r] )
return i + 1
Abstraction faite de la méthode de choix du pivot, dans quelles situations l’une est-elle préférable à l’autre? Je sais par exemple que Lomuto est relativement peu performant lorsqu'il existe un pourcentage élevé de valeurs en double (c'est-à-dire lorsque plus de 2 tiers de la matrice est la même valeur), alors que Hoare se comporte très bien dans cette situation.
Quels autres cas spéciaux rendent une méthode de partition significative mieux que l'autre?
algorithms
sorting
quicksort
Robert S. Barnes
la source
la source
A[i+1] <= x
. Dans un tableau trié (et avec des pivots raisonnablement choisis), Hoare n'échange presque pas et Lomuto en fait une tonne (une fois que j est devenu assez petit, puis tout leA[j] <= x
.) Que me manque-t-il?swap(A[p], A[j])
à la fin de Hoare pour obtenir le même comportement pour les deux.i < j
dans les 2 boucles de répétition du partitionnement de Hoare.Réponses:
Dimension pédagogique
En raison de sa simplicité, la méthode de partitionnement de Lomuto pourrait être plus facile à mettre en œuvre. Il y a une belle anecdote dans la Programmation de Jon Bentley sur le tri:
Dimension de performance
Pour une utilisation pratique, la facilité de mise en œuvre pourrait être sacrifiée pour des raisons d'efficacité. Sur une base théorique, nous pouvons déterminer le nombre de comparaisons d’éléments et d’échanges pour comparer les performances. De plus, le temps d'exécution réel sera influencé par d'autres facteurs, tels que les performances de la mise en cache et les prédictions erronées des branches.
Comme indiqué ci-dessous, les algorithmes se comportent de manière très similaire sur les permutations aléatoires, à l' exception du nombre de swaps . Là-bas, Lomuto a besoin de trois fois plus que Hoare!
Nombre de comparaisons
Nombre de swaps
Le nombre de swaps est aléatoire pour les deux algorithmes, en fonction des éléments du tableau. Si nous supposons des permutations aléatoires , c'est-à-dire que tous les éléments sont distincts et que chaque permutation des éléments est également probable, nous pouvons analyser le nombre attendu de swaps.
Méthode de Lomuto
Méthode de Hoare
Enfin, nous effectuons une nouvelle moyenne sur toutes les valeurs de pivot pour obtenir le nombre total de swaps attendus pour le partitionnement de Hoare:
(Une description plus détaillée se trouve dans la thèse de ma maîtrise , page 29.)
Motif d'accès mémoire
Les deux algorithmes utilisent deux pointeurs dans la matrice qui l’analysent séquentiellement . Par conséquent, les deux se comportent de manière presque optimale en ce qui concerne la mise en cache.
Eléments identiques et listes déjà triées
Comme déjà mentionné par Wandering Logic, les performances des algorithmes diffèrent plus radicalement pour les listes qui ne sont pas des permutations aléatoires.
A[j] <= x
Conclusion
La méthode de Lomuto est simple et facile à mettre en œuvre, mais ne devrait pas être utilisée pour mettre en œuvre une méthode de tri de bibliothèque.
la source
Quelques commentaires ont été ajoutés à l'excellente réponse de Sebastian.
Je vais parler de l’algorithme de réorganisation des partitions en général et non de son utilisation particulière pour Quicksort .
La stabilité
L'algorithme de Lomuto est semistable : l'ordre relatif des éléments ne satisfaisant pas le prédicat est conservé. L'algorithme de Hoare est instable.
Modèle d'accès d'élément
L'algorithme de Lomuto peut être utilisé avec une liste à liens simples ou des structures de données similaires similaires. L'algorithme de Hoare a besoin d'une bidirectionnalité .
Nombre de comparaisons
Mais pour ce faire, nous devons sacrifier 2 propriétés:
la source