¿Cuándo se usa cada algoritmo de clasificación? [cerrado]

170

¿Cuáles son los casos de uso cuando se prefiere un algoritmo de ordenación en particular sobre otros: fusionar ordenación vs QuickSort vs heapsort vs 'intro sort', etc.?

¿Existe una guía recomendada para usarlos en función del tamaño, tipo de estructura de datos, memoria y caché disponibles y rendimiento de la CPU?

sam
fuente
Se puede encontrar un conjunto de animaciones para diferentes tipos de datos y algoritmos en <a href=" sorting-algorithms.com/"> sorting-algorithms.com </ a >
Chip Uni
2
Una guía como bigocheatsheet.com para estas cosas sería genial
K - La toxicidad en SO está creciendo.
@ChipUni aquí está el enlace fijo: toptal.com/developers/sorting-algorithms
eric
2
¿Por qué esta pregunta cerrada?
Arvand

Respuestas:

316

Primero, una definición, ya que es bastante importante: una ordenación estable es aquella que garantiza no reordenar elementos con claves idénticas.

Recomendaciones:

Clasificación rápida: cuando no necesita una clasificación estable y el rendimiento promedio del caso es más importante que el peor de los casos. Una ordenación rápida es O (N log N) en promedio, O (N ^ 2) en el peor de los casos. Una buena implementación utiliza el almacenamiento auxiliar O (log N) en forma de espacio de pila para la recursividad.

Ordenar por fusión: cuando necesita una ordenación estable, O (N log N), esta es su única opción. El único inconveniente es que usa espacio auxiliar O (N) y tiene una constante ligeramente mayor que una clasificación rápida. Hay algunos tipos de fusión en el lugar, pero AFAIK no son todos estables o peor que O (N log N). Incluso los tipos O (N log N) en el lugar tienen una constante mucho mayor que el tipo de fusión simple que son más curiosidades teóricas que algoritmos útiles.

Clasificación de almacenamiento dinámico: cuando no necesita una ordenación estable y le importa más el rendimiento del peor de los casos que el rendimiento promedio del caso. Se garantiza que sea O (N log N), y utiliza O (1) espacio auxiliar, lo que significa que no se quedará sin espacio de pila o montón de forma inesperada en entradas muy grandes.

Introsort: esta es una ordenación rápida que cambia a una ordenación de montón después de una cierta profundidad de recursión para evitar el peor caso de O (N ^ 2) de ordenación rápida. Casi siempre es mejor que una clasificación rápida simple, ya que obtienes el caso promedio de una clasificación rápida, con un rendimiento garantizado de O (N log N). Probablemente, la única razón para usar una ordenación de montón en lugar de esto es en sistemas con limitaciones severas de memoria donde el espacio de pila O (log N) es prácticamente significativo.

Clasificación de inserción : cuando se garantiza que N es pequeño, incluso como el caso base de una clasificación rápida o una combinación. Si bien esto es O (N ^ 2), tiene una constante muy pequeña y es un tipo estable.

Clasificación de burbujas, clasificación de selección : cuando estás haciendo algo rápido y sucio y, por alguna razón, no puedes usar el algoritmo de clasificación de la biblioteca estándar. La única ventaja que tienen sobre el tipo de inserción es que es un poco más fácil de implementar.


Clases de no comparación: en algunas condiciones bastante limitadas, es posible romper la barrera O (N log N) y clasificar en O (N). Aquí hay algunos casos en los que vale la pena intentarlo:

Conteo ordenado: cuando está ordenando enteros con un rango limitado.

Clasificación de radix: cuando log (N) es significativamente mayor que K, donde K es el número de dígitos de radix.

Clasificación de cubetas: cuando puede garantizar que su entrada se distribuye aproximadamente de manera uniforme.

dsimcha
fuente
1
Como recuerdo, la ordenación del montón también tiene un tiempo de ejecución muy predecible, ya que hay poca variación entre las diferentes entradas del mismo tamaño, pero eso es menos interesante que su límite de espacio constante. También encuentro que el tipo de inserción es el más fácil de implementar de los n ^ 2, pero tal vez solo soy yo. Finalmente, es posible que también desee mencionar la ordenación de Shell, que es casi tan simple de implementar como la ordenación por inserción pero tiene un mejor rendimiento, aunque todavía no es n log n.
JaakkoK
29
¡No te olvides de Bogosort ! ;-)
Alex Brasetvik
2
+1 Muy interesante. ¿Le gustaría explicar cómo puede "garantizar ... distribuido aproximadamente de manera uniforme". para la clasificación del cubo?
Sam Overton
2
¿Por qué el introsort sería sustancialmente más lento que la clasificación rápida? La única sobrecarga es contar la profundidad de recursión, que debería ser insignificante. Solo cambia después de que la recursividad es mucho más profunda de lo que debería ser en un buen caso de clasificación rápida.
dsimcha
2
¡No menciona que el mejor caso de clasificación de burbujas es O (n)!
Tara
33

Quicksort suele ser el más rápido en promedio, pero tiene algunos comportamientos bastante desagradables en el peor de los casos. Entonces, si tiene que garantizar que no le brinden datos incorrectos O(N^2), debe evitarlo.

Merge-sort utiliza memoria adicional, pero es particularmente adecuado para la ordenación externa (es decir, archivos enormes que no caben en la memoria).

Heap-sort puede ordenar en el lugar y no tiene el peor comportamiento cuadrático, pero en promedio es más lento que el de clasificación rápida en la mayoría de los casos.

Cuando solo están involucrados enteros en un rango restringido, puede usar algún tipo de clasificación de radix para hacerlo muy rápido.

En el 99% de los casos, estará bien con los tipos de biblioteca, que generalmente se basan en la clasificación rápida.

Eli Bendersky
fuente
66
+1: para "En el 99% de los casos, estará bien con los tipos de biblioteca, que generalmente se basan en la clasificación rápida".
Jim G.
El pivote aleatorio le da a Quicksort un tiempo de ejecución de O (nlogn) para todos los fines prácticos, sin necesidad de garantías sobre datos incorrectos. Realmente no creo que nadie implemente una clasificación rápida O (n ^ 2) para ningún código de producción.
MAK
2
MAK, excepto, digamos, la biblioteca estándar C qsort? ( google.com/codesearch/… ) - en el que se basa la mayor parte del "código de producción"
Eli Bendersky
La ordenación de la biblioteca generalmente no se basa en la clasificación rápida, porque no es estable. Casi todos los lenguajes superiores (espere para C) proporcionan un tipo estable. En la mayoría de los casos, sé que necesita un tipo estable, o al menos determinista.
12431234123412341234123
3

Lo que los enlaces proporcionados a las comparaciones / animaciones no consideran es cuando la cantidad de datos excede la memoria disponible, momento en el cual el número de pases sobre los datos, es decir, los costos de E / S, dominan el tiempo de ejecución. Si necesita hacer eso, lea sobre "clasificación externa" que generalmente cubre variantes de tipos de combinación y montón.

http://corte.si/posts/code/visualisingsorting/index.html y http://corte.si/posts/code/timsort/index.html también tienen algunas imágenes interesantes que comparan varios algoritmos de clasificación.

Alex Brasetvik
fuente
0

@dsimcha escribió: Conteo ordenado: cuando está ordenando enteros con un rango limitado

Cambiaría eso a:

Orden de conteo: cuando ordena enteros positivos (0 - Integer.MAX_VALUE-2 debido al casillero).

Siempre puede obtener los valores máximo y mínimo como una heurística de eficiencia en tiempo lineal también.
También necesita al menos n espacio adicional para la matriz intermedia y obviamente es estable.

/**
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
* OutOfMemoryError: Requested array size exceeds VM limit
*/
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

(aunque en realidad permitirá MAX_VALUE-2) ver: ¿Las matrices Java tienen un tamaño máximo?

También explicaría que la complejidad de clasificación de radix es O (wn) para n claves que son enteros de tamaño de palabra w. A veces, w se presenta como una constante, lo que haría que la ordenación por radix fuera mejor (para un n suficientemente grande) que los mejores algoritmos de ordenación basados ​​en la comparación, que realizan comparaciones O (n log n) para ordenar n claves. Sin embargo, en general, w no puede considerarse una constante: si todas las claves n son distintas, entonces w debe ser al menos log n para que una máquina de acceso aleatorio pueda almacenarlas en la memoria, lo que da como máximo una complejidad de tiempo O (n log n). (de wikipedia)

Droid Teahouse
fuente