Solucion
(a) Particionamiento de Lomuto
Partimos de A=[15,3,9,8,5,2,7,1,6] (indices 0 a 8). Con la particion de Lomuto el pivote es el ultimo elemento, A[8]=6. Usamos dos indices:
- i = frontera de los elementos ≤ pivote (empieza en lo−1=−1).
- j = elemento que estamos examinando (recorre de lo a hi−1).
La regla es: si A[j]≤pivote, avanzamos i e intercambiamos A[i]↔A[j].
| j | A[j] | A[j]≤6? | Accion | Arreglo tras el paso |
|---|
| 0 | 15 | No | j avanza | [15, 3, 9, 8, 5, 2, 7, 1, 6] |
| 1 | 3 | Si | i=0, swap A[0]↔A[1] | [3, 15, 9, 8, 5, 2, 7, 1, 6] |
| 2 | 9 | No | j avanza | [3, 15, 9, 8, 5, 2, 7, 1, 6] |
| 3 | 8 | No | j avanza | [3, 15, 9, 8, 5, 2, 7, 1, 6] |
| 4 | 5 | Si | i=1, swap A[1]↔A[4] | [3, 5, 9, 8, 15, 2, 7, 1, 6] |
| 5 | 2 | Si | i=2, swap A[2]↔A[5] | [3, 5, 2, 8, 15, 9, 7, 1, 6] |
| 6 | 7 | No | j avanza | [3, 5, 2, 8, 15, 9, 7, 1, 6] |
| 7 | 1 | Si | i=3, swap A[3]↔A[7] | [3, 5, 2, 1, 15, 9, 7, 8, 6] |
Al terminar el bucle colocamos el pivote en su lugar intercambiando A[i+1]↔A[hi], es decir A[4]↔A[8]:
A=[3,5,2,1,6,9,7,8,15]
En esta primera particion se hicieron 8 comparaciones y 5 intercambios.
La visualizacion siguiente ejecuta la traza completa (no solo la primera particion, sino todas las llamadas recursivas hasta ordenar el arreglo). Usa los controles para avanzar paso a paso: el morado es el pivote, el ambar el elemento comparado, el rojo un intercambio y el verde los elementos ya ubicados en su posicion definitiva.
(b) Resultado de la particion
Tras la primera particion el pivote 6 queda en el indice 4, que es su posicion definitiva en el arreglo ordenado:
- Subarreglo izquierdo (elementos ≤6): [3,5,2,1] en los indices 0..3.
- Pivote: 6 en el indice 4.
- Subarreglo derecho (elementos >6): [9,7,8,15] en los indices 5..8.
Quick Sort continua recursivamente sobre los subarreglos izquierdo y derecho, que son independientes. El arreglo final ordenado es:
[1,2,3,5,6,7,8,9,15]
(c) Peor caso: arreglo ya ordenado
Para B=[1,2,3,4,5,6,7,8,9] con pivote = ultimo elemento, el pivote es siempre el maximo del subarreglo. Entonces en cada particion todos los elementos cumplen A[j]≤pivote: el indice i avanza en cada paso con i=j (no hay intercambios reales) y el pivote termina en su propia posicion final. La particion produce:
- un subarreglo izquierdo de tamano n−1 (todo menos el pivote), y
- un subarreglo derecho vacio.
El tamano solo disminuye en 1 por nivel, generando una recursion de profundidad n:
T(n)=T(n−1)+(n−1),T(1)=0
El numero total de comparaciones es:
(n−1)+(n−2)+⋯+1+0=∑k=1n−1k=2n(n−1)
Para n=9: 8+7+6+5+4+3+2+1=36 comparaciones. Como 2n(n−1)=21n2−21n=Θ(n2), la complejidad en este caso es O(n2). Ironicamente, un arreglo ya ordenado es el peor caso para esta variante de Quick Sort.
(d) Como evitar el peor caso
- Pivote aleatorio. Antes de particionar se elige un indice al azar en [lo,hi] y se intercambia con A[hi]. Ningun patron fijo de entrada (como un arreglo ordenado) puede provocar el peor caso sistematicamente; el tiempo esperado pasa a ser O(nlogn).
- Mediana de tres. Se toma la mediana entre A[lo], A[⌊(lo+hi)/2⌋] y A[hi] como pivote. Sobre datos casi ordenados produce particiones mucho mas balanceadas y elimina el peor caso en la practica.
Complementos habituales: cambiar a Insertion Sort para subarreglos pequenos (menos overhead) y, para garantizar O(nlogn) incluso en el peor caso, usar Introsort (Quick Sort que cae a Heap Sort cuando la profundidad de recursion supera 2logn).
(e) Estabilidad
Quick Sort (Lomuto) NO es estable: puede alterar el orden relativo de elementos con clave igual.
Contraejemplo. Sea el arreglo de pares (ordenando por el primer componente) [3a, 3b, 1], donde 3a y 3b tienen la misma clave 3 pero 3a aparece antes. Con pivote =A[hi]=1: ningun elemento es ≤1, asi que i se queda en −1 y al final se intercambia A[i+1]=A[0]↔A[2]:
[3a, 3b, 1]⟶[1, 3b, 3a]
Ahora 3b aparece antes que 3a: se invirtio el orden original de dos elementos iguales, por lo que la ordenacion no es estable.