Hay dos métodos de partición de clasificación rápida mencionados en 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
y:
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
Sin tener en cuenta el método de elegir el pivote, ¿en qué situaciones es preferible uno al otro? Sé, por ejemplo, que Lomuto se realiza relativamente mal cuando hay un alto porcentaje de valores duplicados (es decir, donde más de 2/3 la matriz tiene el mismo valor), mientras que Hoare funciona bien en esa situación.
¿Qué otros casos especiales hacen que un método de partición sea significativamente mejor que el otro?
algorithms
sorting
quicksort
Robert S. Barnes
fuente
fuente
A[i+1] <= x
. En una matriz ordenada (y dados los pivotes razonablemente elegidos) Hoare casi no cambia y Lomuto hace una tonelada (una vez que j se vuelve lo suficientemente pequeña, entonces todo lo demásA[j] <= x
). ¿Qué me estoy perdiendo?swap(A[p], A[j])
al final de Hoare para obtener el mismo comportamiento para ambos.i < j
en los 2 bucles de repetición de la partición de Hoare.Respuestas:
Dimensión pedagógica
Debido a su simplicidad, el método de partición de Lomuto podría ser más fácil de implementar. Hay una bonita anécdota en la Perla de programación de Jon Bentley sobre la clasificación:
Dimensión de rendimiento
Para un uso práctico, la facilidad de implementación podría ser sacrificada en aras de la eficiencia. Sobre una base teórica, podemos determinar el número de comparaciones de elementos y swaps para comparar el rendimiento. Además, el tiempo real de ejecución estará influenciado por otros factores, como el rendimiento del almacenamiento en caché y las predicciones erróneas de las ramas.
Como se muestra a continuación, los algoritmos se comportan de manera muy similar en permutaciones aleatorias, excepto por el número de intercambios . ¡Allí Lomuto necesita tres veces más que Hoare!
Numero de comparaciones
Número de intercambios
El número de intercambios es aleatorio para ambos algoritmos, dependiendo de los elementos en la matriz. Si asumimos permutaciones aleatorias , es decir, todos los elementos son distintos y cada permutación de los elementos es igualmente probable, podemos analizar el número esperado de intercambios.
Método de Lomuto
Método de Hoare
Finalmente, promediamos nuevamente sobre todos los valores de pivote para obtener el número total esperado de swaps para la partición de Hoare:
(Se puede encontrar una descripción más detallada en mi tesis de maestría , página 29).
Patrón de acceso a memoria
Ambos algoritmos usan dos punteros en la matriz que lo escanean secuencialmente . Por lo tanto, ambos se comportan con un almacenamiento en memoria caché casi óptimo.
Elementos iguales y listas ya ordenadas
Como ya mencionó Wandering Logic, el rendimiento de los algoritmos difiere más drásticamente para las listas que no son permutaciones aleatorias.
A[j] <= x
Conclusión
El método de Lomuto es simple y más fácil de implementar, pero no debe usarse para implementar un método de clasificación de bibliotecas.
fuente
Algunos comentarios añadidos a la excelente respuesta de Sebastián.
Voy a hablar sobre el algoritmo de reordenamiento de partición en general y no sobre su uso particular para Quicksort .
Estabilidad
El algoritmo de Lomuto es semiestable : se preserva el orden relativo de los elementos que no satisfacen el predicado . El algoritmo de Hoare es inestable.
Patrón de acceso a elementos
El algoritmo de Lomuto se puede usar con una lista vinculada individualmente o estructuras de datos similares de solo avance. El algoritmo de Hoare necesita bidireccionalidad .
Numero de comparaciones
Pero para hacer esto tenemos que sacrificar 2 propiedades:
fuente