¿Cuál es el algoritmo de clasificación de espacio constante más eficiente?

19

Estoy buscando un algoritmo de ordenación para matrices int que no asigne ningún byte que no sea el tamaño de la matriz, y se limita a dos instrucciones:

  1. SWAP: intercambia el siguiente índice con el actual;

  2. MOVER: mueve el cursor al índice +1 o -1;

Es decir, no puede intercambiar índices no vecinos, ni intercambiar el índice 100, después de haber intercambiado el índice 10. ¿Cuál es el algoritmo más eficiente, es decir, el que usa la menor cantidad de movimientos totales?

MaiaVictor
fuente
13
No es extraño, es una máquina física que clasificará una lista de carros pegados a una cinta que se enrolla. La máquina solo puede mover la cinta hacia adelante o hacia atrás, y solo puede intercambiar cartas vecinas, de corse. En el mundo real no puedes teletransportarte, así que esas son las restricciones ...
MaiaVictor
2
Entonces, cuando dice que desea un algoritmo que no asigne ningún byte que no sea el tamaño de la matriz , supongo que se refiere solo al almacenamiento de elementos, ¿verdad? ¿Todavía puedo asignar contadores y tal?
Darkhogg
55
Oh, por supuesto. Por supuesto. Puede asignar algunas estructuras adicionales. Incluso puede asignar toda la matriz y hacer muchos cálculos realmente pesados ​​y eso cuenta como costo 0. Lo único que debe minimizar es la cantidad de SWAP / MOVE de la máquina física real, porque es lenta. Lo mejor que pude encontrar fue el tipo de burbuja, pero supuse que debería haber mejores opciones.
MaiaVictor
1
No creo que haya tal algoritmo. Sin ninguna memoria adicional, usted no tiene manera de almacenar cualquier estado de control.
Raphael
1
@svrm: sí, entonces, con RAM ilimitada y la capacidad de copiar la cinta en la RAM y hacer cálculos arbitrarios de forma gratuita, el algoritmo "prueba todo y aplica lo mejor" es óptimo en términos de cantidad de movimientos de la cinta. Es poco probable que sea práctico, pero eso se debe a que, en la práctica, el tiempo de ejecución sería de miles de millones de años, no 0 ;-) Si cuesta N movimientos copiar una cinta de longitud N en la RAM, entonces la fuerza bruta ingenua podría no ser óptima, pero está dentro de N de óptimo. Pero nada de esto es específico para su problema: muchos problemas cuando se establecen de esta manera podrían resolverse "fuera de línea" utilizando un algoritmo falso.
Steve Jessop

Respuestas:

13

Considere el tipo de coctelera , que es una versión bidireccional del tipo burbuja. Usted burbujea de bajo a alto, y luego (esta es la parte añadida) burbujea de alto a bajo, repita hasta que esté listo. Esto sigue siendo , pero hace significativamente menos pases en promedio, porque los elementos pequeños cerca del extremo superior de la matriz se moverán a su posición final en un solo pase en lugar de N pases. Además, puede realizar un seguimiento de las posiciones más bajas y más altas donde se produjo un intercambio; los pases posteriores no necesitan escanear más allá de esos puntos.O(norte2)

zwol
fuente
4

El número de intercambios de elementos adyacentes necesarios para ordenar una matriz es igual a la cantidad de inversiones en la matriz. Con n elementos en total, hay a lo sumo n * (n-1) / 2 inversiones, por lo que la ordenación de burbujas da el número asintóticamente óptimo de intercambios en este modelo.

Charles
fuente
En realidad, la clasificación de burbujas dará exactamente el número óptimo de intercambios. Sin embargo, para cada permutación hay varias formas de hacer el número óptimo de intercambios, y no es obvio cuál reduce el número total de movimientos. (Por ordenamiento de burbuja me refiero a "elegir el no clasificado más grande y moverlo al final del ordenado")
Peter Kravchuk
4

El único algoritmo con los dos operadores que ha mencionado que es bastante eficiente es el tipo de burbuja. La complejidad del algoritmo es O(norte2)

-+

El algoritmo que no usa una bandera booleana para saber si hemos intercambiado algún elemento o no, se da a continuación (el truco para mantener la información en el estado de la máquina, en lugar de la memoria):

Start:
    Do until we are not at the leftmost position (Op 4)
        move left (Op 2b)

Check:
    If we are at rightmost position (Op 3)
        goto Finished:
    If current value is larger than next value (Op 5)
        goto Unfinished:
    move right (Op 2a)
    Repeat Check:

Unfinished:
    If we are at rightmost position (Op 3)
        goto Start:
    If current value is larger than next value (Op 5)
        swap the elements (Op 1) and move right (Op 2a)
    Repeat Unfinished:

Finished:
    The list is sorted now, output it.

La solución de Eric Lippert, el gnomo también funciona, porque básicamente es un tipo de burbuja de dos vías.

Shreesh
fuente
¿Qué pasa con el tipo de inserción?
Darkhogg
La ordenación de burbujas necesita al menos dos contadores de bucles que ya son más de lo permitido.
Raphael
1
No, puede ir a izquierda y derecha, y luego de derecha a izquierda, hasta que no haya cambios (que es máximo n veces) sin usar el contador. Ni siquiera necesita espacio adicional para que una bandera booleana note si hay un cambio. Si hay un cambio, simplemente salta a otra subrutina que hace lo mismo, excepto que es otra subrutina.
Shreesh
1
Y, por supuesto, supongo que puede leer en blanco en ambos extremos para que sepa que es el principio o el final de la lista. Además, supongo que leemos tanto el elemento actual como el siguiente para saber si necesitamos intercambiar.
Shreesh
1
O, si modificamos el intercambio de operador como "intercambio si no en orden ascendente".
Shreesh