¿Cómo es este algoritmo de clasificación Θ (n³) y no Θ (n²), en el peor de los casos?


52

Recién comencé a tomar un curso sobre estructuras de datos y algoritmos y mi asistente de enseñanza nos dio el siguiente pseudocódigo para ordenar una serie de enteros:

void F3() {
    for (int i = 1; i < n; i++) {
        if (A[i-1] > A[i]) {
            swap(i-1, i)
            i = 0
        }
    }
}

Puede que no esté claro, pero aquí es el tamaño de la matriz que estamos tratando de ordenar.nA

En cualquier caso, el asistente de enseñanza explicó a la clase que este algoritmo está en tiempo (el peor de los casos, creo), pero no importa cuántas veces lo revise con una matriz ordenada inversamente, me parece que debería ser y no .Θ ( n 2 ) Θ ( n 3 )Θ(n3)Θ(n2)Θ(n3)

¿Alguien podría explicarme por qué esto es Θ(n3) y no Θ(n2) ?


Puede interesarle un enfoque estructurado para el análisis ; intenta encontrar una prueba tu mismo!
Raphael

Simplemente impleméntelo y mida para convencerse. Una matriz con 10,000 elementos en orden inverso debería tomar muchos minutos, y una matriz con 20,000 elementos en orden inverso debería tomar aproximadamente ocho veces más.
gnasher729

@ gnasher729 No está equivocado, pero mi solución es diferente: si intenta probar su límite , siempre fallará, lo que le indicará que algo anda mal. (Por supuesto, uno puede hacer ambas cosas. El trazado / ajuste es definitivamente más rápido para rechazar hipótesis, pero menos confiable . Siempre y cuando haga algún tipo de análisis formal / estructurado, no hay daño. Confiar en las parcelas es donde comienzan los problemas)O(n2)
Rafael

1
debido a la i = 0declaración
njzk2

Respuestas:


60

Este algoritmo se puede reescribir así

  1. Escanee Ahasta que encuentre una inversión .
  2. Si encuentra uno, intercambie y comience de nuevo.
  3. Si no hay ninguno, finalice.

Ahora puede haber como máximo inversiones y necesita una exploración de tiempo lineal para encontrar cada una, por lo que el peor tiempo de ejecución es . ¡Un hermoso ejemplo de enseñanza, ya que dispara el enfoque de coincidencia de patrones que muchos sucumben!(n2)Θ(n2)Θ(n3)

Nota bene: Hay que tener un poco de cuidado: algunas inversiones aparecen temprano, otras tarde, por lo que no es trivial en sí mismo que los costos se sumen como se afirma (para el límite inferior). También debe observar que los intercambios nunca introducen nuevas inversiones. Un análisis más detallado del caso con la matriz ordenada inversamente arrojará algo así como el caso cuadrático de la fórmula de Gauss.

Como @ gnasher729 comenta acertadamente, es fácil ver que el peor tiempo de ejecución es analizando el tiempo de ejecución al ordenar la entrada (aunque esta entrada probablemente no sea el peor de los casos).Ω(n3)[1,2,,n,2n,2n1,,n+1]

Tenga cuidado: no asuma que una matriz ordenada inversamente será necesariamente la peor entrada para todos los algoritmos de clasificación. Eso depende del algoritmo. Hay algunos algoritmos de ordenación en los que una matriz ordenada inversamente no es el peor de los casos, e incluso podría estar cerca del mejor.


14
Si toma una matriz donde la primera mitad consiste en los números 1 a n / 2 en orden ascendente, y la segunda mitad es n a n / 2 + 1 en orden inverso, entonces es obvio que necesita al menos n / 2 pasos para encontrar cada inversión, y habrá aproximadamente (n / 2) ^ 2/2 de ellos. Y probablemente no sea el peor de los casos.
gnasher729

@AnthonyRossello Es un resultado estándar (en combinatoria de permutaciones). En resumen, cuente el número de inversiones en la matriz ordenada inversamente (¿es obvio que ese es el peor de los casos?); Es una suma de Gauss.
Raphael

Hay que recordar que no importa qué, las sumas parciales de son siempre , es solo el coeficiente que cae rápidamente: (tenga en cuenta el coeficiente bastante grande ). El problema es que a no le importan los coeficientes. Θ(nα)Θ(nα+1)k=0nkα1α+1nα+11α+1Θ
yo'

2
@yo 'Y esto se relaciona con la respuesta (o la pregunta) ¿cómo?
Raphael

7

Una forma alternativa de pensar sobre esto es en lo que se iconvierte el valor máximo de antes de restablecerlo. Resulta que esto hace que sea más sencillo razonar sobre cómo el orden de clasificación anterior Aafecta el tiempo de ejecución del algoritmo.

En particular, observe que cuando iestablece su nuevo valor máximo, llamémoslo N, la matriz [A[0], ..., A[N-1]]se ordena en orden ascendente.

Entonces, ¿qué sucede cuando agregamos el elemento A[N]a la mezcla?

Las matemáticas:

Bueno, digamos que encaja en la posición . Luego necesitamos iteraciones de bucle (que denotaré ) para moverlo a , iteraciones para moverlo a y, en general:pNNstepsN1N+(N1)N2

stepsN(pN)=N+(N1)+(N2)++(pN+1)=12(N(N+1)pN(pN+1))

Para una matriz ordenada aleatoriamente, toma la distribución uniforme en para cada , con:pN{0,1,,N}N

E(stepsN(pN))=a=1NP(pN=a)stepsN(a)=a=1N1N12(N(N+1)a(a+1))=12(N(N+1)13(N+1)(N+2))=13(N21)=Θ(N2)

la suma se puede mostrar usando la fórmula de Faulhaber o el enlace Wolfram Alpha en la parte inferior.

Para una matriz inversamente ordenada, para todo , y obtenemos:pN=0N

stepsN(pN)=12N(N+1)

exactamente, tomando estrictamente más tiempo que cualquier otro valor de .pN

Para una matriz ya ordenada, y , y los términos de orden inferior se vuelven relevantes.pN=NstepsN(pN)=0

Tiempo Total:

Para obtener el tiempo total, resumimos los pasos de toda la hacienda . (Si fuéramos muy cuidadosos, resumiríamos los intercambios, así como las iteraciones del bucle, y nos ocuparíamos de las condiciones de inicio y finalización, pero es razonablemente fácil ver que no contribuyen a la complejidad en la mayoría de los casos) .N

Y nuevamente, usando la linealidad de la expectativa y la fórmula de Faulhaber:

Expected Total Steps=E(N=1nstepsN(pN))=N=1nE(stepsN(pN))=Θ(n3)

Por supuesto, si por alguna razón no es (por ejemplo, la distribución de las matrices que estamos viendo ya está muy cerca de ser ordenada), entonces esto no siempre necesita sea ​​el caso. ¡Pero se necesitan distribuciones muy específicas en para lograr esto!stepsN(pN)Θ(N2)pN

Lectura relevante:


@Raphael: gracias por las mejoras sugeridas, he agregado un poco más de detalles. Bueno, las variables aleatorias son (de , el conjunto de ordenaciones de ), por lo que las expectativas se hacen técnicamente sobrepiΩAΩ
David E

Diferente ; Me refería al Landau. Ω
Raphael

3

Descargo de responsabilidad:

Esto no es una prueba (parece que algunas personas piensan que lo publiqué como si lo fuera). Este es solo un pequeño experimento que el OP podría realizar para resolver sus dudas sobre la tarea:

no importa cuántas veces lo revise con una matriz ordenada inversamente, me parece que debería ser y no .Θ(n2)Θ(n3)

Con un código tan simple, la diferencia entre y no debería ser difícil de detectar y, en muchos casos prácticos, este es un enfoque útil para verificar corazonadas o ajustar las expectativas.Θ(n2)Θ(n3)


@Raphael ya respondió su pregunta, pero solo por patadas, ajustando la salida de este programa a usando este script gnuplot reportó valores de exponente de y y produjo los siguientes gráficos ( el primero es la escala normal y el segundo es la escala log-log):f(x)=axb+cx2.997961668332222.99223727692339

normal loglog

Espero que esto ayude¨


2
Puede ajustar cualquier función a estos valores. Ver también aquí .
Raphael

3
@Raphael Si no quieres hacer trampas de esta manera, entonces no, no puedes ajustar ninguna función (por ejemplo, no podrás ajustar una función constante con una precisión razonable). Esto no es una prueba, pero ya hay una respuesta que proporciona un boceto. En cuanto a la utilidad, puedo citar su propia publicación que vinculó: "Tengo que estar de acuerdo en que este es un enfoque muy útil que incluso a veces se subutiliza". Además, el OP dijo que pensaba que debería ser lugar de , entonces, ¿por qué no experimentar y ver si su presentimiento era correcto? Cont. Θ(n2)Θ(n3)
dtldarek

2
Esto proporciona evidencia de que el algoritmo es pero la pregunta pregunta por qué . Pide una explicación del fenómeno, no una confirmación del mismo. Θ(n3)
David Richerby

2
@DavidRicherby ¿Significa esto que esta respuesta no es útil?
dtldarek

3
@Magicsowon Es un sitio de preguntas y respuestas, no un foro. Estamos buscando respuestas a la pregunta, no discusiones al respecto.
David Richerby

3

Suponga que tiene una matriz.

array a[10] = {10,8,9,6,7,4,5,2,3,0,1}

Su algoritmo hace lo siguiente

Scan(1) - Swap (10,8) => {8,10,9,6,7,4,5,2,3,0,1}  //keep looking at "10"
Scan(2) - Swap (10,9) => {8,9,10,6,7,4,5,2,3,0,1}
...
Scan(10) - Swap(10,1) => {8,9,6,7,4,5,2,3,0,1,10}

Básicamente, mueve hasta el final de la matriz el elemento más alto, y al hacerlo, comienza de nuevo en cada exploración efectivamente haciendo O(n^2)movimientos ... solo para ese elemento. Sin embargo, hay n elementos, así que tendremos que repetirlo esta nvez. Esta no es una prueba formal, pero ayuda a comprender de manera "no formal" por qué es el tiempo de ejecución O(n^3).


44
¿Qué agrega esto sobre otras respuestas? Ya se dio una explicación de lo que hace el algoritmo, y su razonamiento para el tiempo de ejecución es incompleto en el mejor de los casos. (¡El peor de los casos no se comporta linealmente!)
Raphael

2
A veces hay valor en explicar la misma idea de múltiples maneras (con formalismo; con un ejemplo simple para "bombear la intuición"), especialmente cuando la persona que hace la pregunta es nueva en el campo. Entonces, me parece que esto agrega que se presenta de una manera que podría ayudar a la intuición.
DW

Desde que recibí una respuesta a mi comentario en una bandera (¡no hagas eso!): "¡El peor de los casos no se comporta linealmente!" - Me refiero a las propiedades algebraicas del peor de los operadores. En términos generales, está utilizando WorstCase (1 + ... + n) "=" WorstCase (1) + ... + WorstCase (n) pero esta identidad no se mantiene.
Raphael

1
Soy nuevo en este campo y proporcionar una explicación con un ejemplo concreto y detallado definitivamente me ayudó a ganar intuición sobre el problema. Ahora la solución aceptada tiene más sentido para mí.
vaer-k

0

La lógica parece estar ordenando los elementos en la matriz en orden ascendente.

Supongamos que el número más pequeño está al final de la matriz (a [n]). Para que llegue a su lugar correcto - (n + (n-1) + (n-2) + ... 3 + 2 + 1) se requieren operaciones. = O (n2).

Para un solo elemento en la matriz O (n2) se requieren operaciones. Entonces, para los elementos es O (n3).


55
¿Qué agrega esto sobre otras respuestas? Ya se dio una explicación de lo que hace el algoritmo, y su razonamiento para el tiempo de ejecución es incompleto en el mejor de los casos. (¡El peor de los casos no se comporta linealmente!)
Raphael

Gran explicación Esto proporciona una perspectiva diferente y más intuitiva del problema, que no se explica en otras respuestas. (Sin mencionar que es muy breve y fácil de entender).
2501

1
@ 2501 No, está mal. Intente usar esta "intuición" en el algoritmo de Dijkstra y obtendrá un tiempo de ejecución cuadrático (en el número de nodos), lo cual está mal.
Raphael

@Raphael No, es correcto, como se explica en la respuesta. Esta explicación funciona para este algoritmo, no para otros. Si bien puede ser incorrecto para ellos, este reclamo no prueba que sea incorrecto para este.
2501

@Raphael No entendí la explicación en la respuesta aceptada. Entonces, resolví esto y traté de explicarlo en términos simples sin ningún término técnico ... por lo tanto, esto es para miembros como yo que no podían entender la respuesta aceptada ... Me alegra que alguien encuentre esto útil.
mk ..
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.