¿Qué algoritmo de clasificación funciona mejor en los datos ordenados principalmente? [cerrado]

174

¿Qué algoritmo de clasificación funciona mejor en la mayoría de los datos ordenados?

gráficos
fuente
Adivinando por falta de contexto: ¿está preguntando sobre una clasificación en memoria sin necesidad de derramar resultados intermedios al disco?
Jonathan Leffler
1
De acuerdo con estas animaciones, la ordenación por inserción funciona mejor en la mayoría de los datos ordenados.
dopple el

Respuestas:

259

Basado en el método altamente científico de ver gifs animados , diría que los tipos de inserción y burbuja son buenos candidatos.

Tom Ritter
fuente
19
eso es un excelente enlace por cierto, felicitaciones y un 1
ninesided
55
El tipo de burbuja es terrible. Siempre es O (n ^ 2). Al menos, retíralo de tu respuesta para que sea correcto, por favor.
jjnguy
79
jjnguy, eso es simplemente incorrecto. Creo que necesitas volver a tomar tu clase de algoritmos. En datos casi ordenados (es un caso adaptativo) es O (N). Sin embargo, toma 2 pasadas a través de los datos y la inserción solo toma 1 para datos casi ordenados, lo que hace que la inserción sea la ganadora. Sin embargo
mmcdole
3
Sin embargo, el rendimiento se degrada muy mal si sus datos nunca se ordenan. Todavía no lo usaría, personalmente.
Blorgbeard sale el
55
Ese enlace se rompió cuando lo probé. Pruebe esto en su lugar: sorting-algorithms.com
Michael La Voie
107

Solo unos pocos elementos => ORDEN DE INSERCIÓN

La mayoría de los artículos ya están ordenados => ORDEN DE INSERCIÓN

Preocupado por los peores escenarios => HEAP SORT

Interesado en un buen resultado de caso promedio => QUICKSORT

Los elementos se extraen de un universo denso => ​​ORDEN DE CUBO

Deseo de escribir el menor código posible => ORDEN DE INSERCIÓN

Jiaji Li
fuente
1
Ese es exactamente el tipo de respuesta que he estado buscando, leí libros, pero no encuentro ninguna explicación clara para la selección de alogoritmos en casos particulares, ¿podría elaborar esto o pasar un enlace para que pueda profundizar en es un poco mas? Gracias
Simran kaur
9
Debe agregar "Los datos ya están ordenados por otro criterio => MERGE SORT"
Jim Hunziker
30

timsort

Timsort es "un mergesort natural adaptable, estable" con " rendimiento sobrenatural en muchos tipos de matrices parcialmente ordenadas (se necesitan menos de 1g (N!) Comparaciones y tan pocas como N-1)". Python incorporadosort()ha usado este algoritmo por algún tiempo, aparentemente con buenos resultados. Está específicamente diseñado para detectar y aprovechar subsecuencias parcialmente ordenadas en la entrada, que a menudo ocurren en conjuntos de datos reales. A menudo es el caso en el mundo real que las comparaciones son mucho más caras que intercambiar elementos en una lista, ya que uno simplemente intercambia punteros, lo que a menudo hace que timsort sea una excelente opción. Sin embargo, si sabe que sus comparaciones siempre son muy baratas (por ejemplo, escribir un programa de juguete para clasificar enteros de 32 bits), existen otros algoritmos que probablemente tengan un mejor rendimiento. La forma más fácil de aprovechar timsort es, por supuesto, usar Python, pero dado que Python es de código abierto, también puede pedir prestado el código. Alternativamente, la descripción anterior contiene detalles más que suficientes para escribir su propia implementación.

zaphod
fuente
16
log (n!) es Ο (n * log (n)) por lo tanto, no es "sobrenatural".
jfs
Aquí está la implementación de Java que viene en JDK7: cr.openjdk.java.net/~martin/webrevs/openjdk7/timsort/raw_files/…
Tim
log (n!) no es rápido. wolframalpha.com/input/?i=plot[log(N!) , {N, 0,1000}]
Behrooz
9
@JF Sebastian: ¡timsort es mucho más rápido que las lg(n!)comparaciones en una matriz casi ordenada, hasta el final O(n)! El | @behrooz: Ningún tipo de comparación puede tener un caso promedio mejor que O(n log n), y lg(n!)es O(n log n). Entonces, el peor caso de Timsort es asintóticamente no peor que el de cualquier otro tipo de comparación. Además, su mejor caso es mejor o igual que cualquier otro tipo de comparación.
Artelius
3
Timsort sigue siendo O (nlogn) en el peor de los casos, pero sus buenos casos son bastante agradables. Aquí hay una comparación, con algunos gráficos: stromberg.dnsalias.org/~strombrg/sort-comparison Tenga en cuenta que timsort en Cython no fue tan rápido como el construido en Python en C.
user1277476
19

Tipo de inserción con el siguiente comportamiento:

  1. Para cada elemento ken las ranuras 1..n, primero verifique si el[k] >= el[k-1]. Si es así, vaya al siguiente elemento. (Obviamente, omita el primer elemento).
  2. De lo contrario, utilice la búsqueda binaria en elementos 1..k-1para determinar la ubicación de inserción, luego pase los elementos. (Es posible hacer esto sólo si k>Ten Tun cierto valor umbral, con un pequeño kesto es una exageración.)

Este método hace el menor número de comparaciones.

Jason Cohen
fuente
Creo que el ordenamiento de burbujas podría superar esto si el número de elementos sin clasificar es muy pequeño (como uno o dos), pero en general esto me parece probablemente la mejor solución.
Sol
Debido al paso 1, para cualquier elemento que ya esté ordenado, hay exactamente una comparación y cero movimientos de datos, que obviamente es lo mejor que puede hacer. El paso 2 es el que podría mejorar, pero la burbuja moverá la misma cantidad de elementos y podría tener más comparaciones, dependiendo de su impl.
Jason Cohen
En realidad, pensándolo mejor, creo que el tipo de burbuja es más fuerte de lo que pensaba. En realidad es una pregunta bastante complicada. Por ejemplo, si toma el caso donde la lista está completamente ordenada, excepto que el elemento que debería ser el último es el primero, la clasificación de burbujas superará ampliamente lo que usted describe.
Sol
Traté de implementar esto, pero la búsqueda binaria no es una gran mejora, ya que todavía tiene que mover todo el bloque para insertar el elemento. Entonces, en lugar de 2xrange, obtienes range + logb (range).
este
11

Prueba el tipo introspectivo. http://en.wikipedia.org/wiki/Introsort

Se basa en la clasificación rápida, pero evita el peor comportamiento que tiene la clasificación rápida para listas casi ordenadas.

El truco es que este algoritmo de clasificación detecta los casos en los que el ordenamiento rápido entra en el peor de los casos y cambia a ordenar o combinar. Las particiones casi ordenadas se detectan mediante algún método de partición no ingenuo y las particiones pequeñas se manejan usando la ordenación por inserción.

Obtiene el mejor de todos los algoritmos de clasificación principales por el costo de un código más complejo. Y puede estar seguro de que nunca se encontrará con el peor comportamiento, sin importar cómo se vean sus datos.

Si es un programador de C ++, verifique su algoritmo std :: sort. Es posible que ya use una ordenación introspectiva internamente.

Nils Pipenbrinck
fuente
7

Splaysort es un oscuro método de clasificación basado en splay trees , un tipo de árbol binario adaptativo. Splaysort es bueno no solo para datos parcialmente ordenados, sino también para datos parcialmente ordenados en reversa, o de hecho, cualquier dato que tenga algún tipo de orden preexistente. Es O (nlogn) en el caso general y O (n) en el caso en que los datos se ordenan de alguna manera (hacia adelante, hacia atrás, organo-pipe, etc.).

Su gran ventaja sobre la ordenación por inserción es que no vuelve al comportamiento O (n ^ 2) cuando los datos no están ordenados en absoluto, por lo que no necesita estar absolutamente seguro de que los datos están ordenados parcialmente antes de usarlos .

Su desventaja es la sobrecarga de espacio adicional de la estructura del árbol de extensión que necesita, así como el tiempo requerido para construir y destruir el árbol de extensión. Pero dependiendo del tamaño de los datos y la cantidad de clasificación previa que espera, la sobrecarga puede valer la pena por el aumento de la velocidad.

Se publicó un documento sobre splaysort en Software - Practice & Experience.

TimB
fuente
5

inserción o tipo de concha!

novedoso
fuente
5

El smoothsort de Dijkstra es un gran tipo de datos ya ordenados. Es una variante de montón que se ejecuta en O (n lg n) en el peor de los casos y O (n) en el mejor de los casos. Yo escribí un análisis del algoritmo, en caso de que usted es curioso cómo funciona.

La combinación natural es otra muy buena para esto: es una variante de combinación ascendente que funciona tratando la entrada como la concatenación de múltiples rangos ordenados diferentes, luego usando el algoritmo de combinación para unirlos. Repite este proceso hasta que se ordene todo el rango de entrada. Esto se ejecuta en tiempo O (n) si los datos ya están ordenados y O (n lg n) en el peor de los casos. Es muy elegante, aunque en la práctica no es tan bueno como otros tipos adaptativos como Timsort o smoothsort.

templatetypedef
fuente
¿Cuáles son las constantes de tiempo de ejecución de smoothsort en comparación con otros algoritmos de clasificación? (es decir, tiempo de ejecución (smoothsort) / tiempo de ejecución (insertionsort) para los mismos datos)
Arne Babenhauserheide
4

Si los elementos ya están ordenados o solo hay pocos elementos, ¡sería un caso de uso perfecto para la inserción de clasificación!

Roger
fuente
3

La ordenación por inserción lleva tiempo O (n + el número de inversiones).

Una inversión es un par (i, j)tal que i < j && a[i] > a[j]. Es decir, un par fuera de servicio.

Una medida de estar "casi ordenado" es el número de inversiones: se podría tomar "datos casi ordenados" como datos con pocas inversiones. Si se sabe que el número de inversiones es lineal (por ejemplo, acaba de agregar elementos O (1) a una lista ordenada), la ordenación por inserción toma tiempo O (n).

Jonas Kölker
fuente
2

Como todos los demás dijeron, tenga cuidado con Quicksort ingenuo, que puede tener un rendimiento O (N ^ 2) en datos ordenados o casi ordenados. Sin embargo, con un algoritmo apropiado para la elección del pivote (ya sea aleatorio o mediana de tres, consulte Elección de un pivote para Quicksort ), Quicksort seguirá funcionando de manera sensata.

En general, la dificultad para elegir algoritmos como la ordenación por inserción radica en decidir cuándo los datos están lo suficientemente desordenados como para que Quicksort sea realmente más rápido.

Jonathan Leffler
fuente
2

No voy a pretender tener todas las respuestas aquí, porque creo que obtener las respuestas reales puede requerir codificar los algoritmos y perfilarlos con muestras de datos representativos. Pero he estado pensando en esta pregunta toda la noche, y esto es lo que se me ha ocurrido hasta ahora, y algunas conjeturas sobre qué funciona mejor y dónde.

Sea N el número total de artículos, M sea el número fuera de servicio.

El ordenamiento de burbujas tendrá que hacer que algo como 2 * M + 1 pase por todos los N elementos. Si M es muy pequeño (0, 1, 2?), Creo que será muy difícil de superar.

Si M es pequeño (digamos menos que log N), la ordenación por inserción tendrá un gran rendimiento promedio. Sin embargo, a menos que haya un truco que no esté viendo, tendrá un rendimiento muy malo en el peor de los casos. (¿Correcto? Si el último elemento del pedido es el primero, debe insertar cada elemento, por lo que puedo ver, lo que matará el rendimiento). Supongo que hay un algoritmo de clasificación más confiable para esto. caso, pero no sé de qué se trata.

Si M es más grande (digamos igual o mayor que log N), la clasificación introspectiva es casi seguramente la mejor.

Excepción a todo eso: si realmente sabe de antemano qué elementos no están clasificados, entonces su mejor opción será extraer esos elementos, ordenarlos usando una clasificación introspectiva y fusionar las dos listas ordenadas en una sola lista ordenada. Si pudiera averiguar rápidamente qué elementos están fuera de servicio, esta también sería una buena solución general, pero no he podido encontrar una manera simple de hacerlo.

Reflexiones adicionales (de la noche a la mañana): si M + 1 <N / M, puede escanear la lista buscando una serie de N / M en una fila ordenada y luego expandir esa serie en cualquier dirección para encontrar la salida -encargar artículos. Eso tomará como máximo 2N comparaciones. A continuación, puede ordenar los elementos sin clasificar y hacer una fusión ordenada en las dos listas. Las comparaciones totales deberían ser inferiores a algo como 4N + M log2 (M), que va a superar cualquier rutina de clasificación no especializada, creo. (Aún más pensado: esto es más complicado de lo que estaba pensando, pero todavía creo que es razonablemente posible).

Otra interpretación de la pregunta es que puede haber muchos artículos fuera de servicio, pero están muy cerca de donde deberían estar en la lista. (Imagínese comenzar con una lista ordenada e intercambiar cualquier otro elemento con el que viene después). En ese caso, creo que la clasificación de burbujas funciona muy bien: creo que el número de pases será proporcional al más alejado fuera de lugar de un elemento es. La ordenación por inserción funcionará mal, porque cada elemento fuera de servicio activará una inserción. Sospecho que el tipo introspectivo o algo así también funcionará bien.

Sol
fuente
1

Si necesita una implementación específica para ordenar algoritmos, estructuras de datos o cualquier cosa que tenga un enlace a lo anterior, ¿podría recomendarle el excelente proyecto "Estructuras de datos y algoritmos" en CodePlex?

Tendrá todo lo que necesita sin reinventar la rueda.

Solo mi pequeño grano de sal.

Maxime Rouiller
fuente
1

Esta buena colección de algoritmos de clasificación para este propósito en las respuestas parece carecer de Gnome Sort , que también sería adecuada, y probablemente requiera el menor esfuerzo de implementación.

haraldkl
fuente
0

La ordenación por inserción es el mejor caso O (n) en la entrada ordenada. Y está muy cerca de la entrada clasificada en su mayoría (mejor que la clasificación rápida).

jjnguy
fuente
0

medita en Probar el montón. Creo que es el más consistente de los tipos O (n lg n).

Paul Nathan
fuente
La consistencia no es motivo de preocupación aquí. Heapsort dará O (n lg n) incluso en datos ordenados, y no es realmente adaptativo. Las opciones viables pueden ser: Ordenación por inserción, Timsort y Bubblesort.
Max
0

El ordenamiento de burbujas (o, más seguro aún, el ordenamiento de burbujas bidireccional) es probablemente ideal para listas clasificadas en su mayoría, aunque apuesto a que un ordenamiento de peine ajustado (con un tamaño de separación inicial mucho más bajo) sería un poco más rápido cuando la lista no No tan perfectamente ordenado. La clasificación de peine se degrada a clasificación de burbujas.

Brian
fuente
0

bueno, depende del caso de uso. Si sabe qué elementos se cambian, eliminar e insertar será el mejor caso en lo que a mí respecta.

Helin Wang
fuente
1
Esta prueba de eficiencia del algoritmo "en lo que a mí concierne" me iluminó el día :) Sin embargo, en serio, al escribir "eliminar e insertar", ¿te refieres a Insertion Sort (que ya se mencionó en respuestas anteriores), u ofreces ¿Un nuevo tipo de algoritmo? Si es así, expanda su respuesta.
yoniLavi
0

El tipo de burbuja es definitivamente el ganador. El siguiente en el radar sería el de inserción.

vCillusion
fuente
44
publique su respuesta con una explicación;
1
Te sugiero que eches un vistazo a las respuestas disponibles antes de publicar para evitar duplicados.
angainor
-1

Manténgase alejado de QuickSort, es muy ineficiente para los datos previamente ordenados. La ordenación por inserción maneja bien los datos casi ordenados moviendo la menor cantidad de valores posible.

Werg38
fuente
-1 Cada implementación industrial de Quicksort tiene una selección de pivote razonable
Stephan Eggermont
1
Sí, pero ninguna selección de pivote es perfecta a menos que sea costosa.
user1277476