FundamentosAlgoritmos

Algoritmos de ordenación

De la burbuja a Timsort — cómo ordenan los algoritmos clásicos, qué es la estabilidad y por qué tu lenguaje ya eligió por ti.

En esta página

Ordenar es el problema más estudiado de la informática — no porque ordenar sea fascinante, sino porque los datos ordenados habilitan todo lo demás: la búsqueda binaria, los rangos, los índices, la deduplicación. Y los algoritmos clásicos de ordenación son el mejor gimnasio que existe para razonar sobre complejidad.

Burbuja: el algoritmo-maestro (para aprender)

La ordenación por burbuja recorre el array comparando pares adyacentes e intercambiándolos si están en desorden. Tras cada pasada, el mayor pendiente “burbujea” hasta su posición final. Míralo trabajar:

function burbuja(arr: number[]): number[] {
  for (let i = 0; i < arr.length - 1; i++) {
    let huboCambios = false;
    // El final ya está ordenado: cada pasada colocó un máximo
    for (let j = 0; j < arr.length - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
        huboCambios = true;
      }
    }
    if (!huboCambios) break; // pasada limpia = ya está ordenado
  }
  return arr;
}

Nadie usa burbuja en producción — es O(n²) — pero enseña tres ideas que reaparecen en todos los demás: la invariante (el tramo final siempre está ordenado), la detección de trabajo terminado (pasada sin cambios → fin), y el análisis del peor caso frente al mejor (array ya ordenado: una sola pasada, O(n)).

La familia O(n²): cuándo cada una

  • Inserción: como ordenar cartas en la mano — toma el siguiente elemento y deslízalo hasta su sitio entre los ya ordenados. Es el mejor de los cuadráticos en la práctica: casi O(n) con datos casi ordenados, y imbatible en arrays pequeños (<20 elementos).
  • Selección: busca el mínimo del resto y colócalo. Siempre O(n²) — hasta con el array ya ordenado — pero hace el mínimo número de intercambios (n−1), útil si escribir es carísimo.
  • Burbuja: la que acabas de ver. Su único mérito práctico es pedagógico.

El salto a O(n log n)

La barrera teórica de la ordenación por comparación es O(n log n) — no existe algoritmo por comparaciones que la baje. Los dos clásicos que la alcanzan usan la misma arma: divide y vencerás.

  • Merge sort: divide el array en dos mitades, ordena cada una recursivamente y mezcla las dos mitades ordenadas (la mezcla es O(n)). Garantiza O(n log n) siempre, es estable, y a cambio usa O(n) de memoria extra.
  • Quicksort: elige un pivote, separa menores a un lado y mayores al otro, y repite en cada lado. Ordena in situ y en la práctica es rapidísimo — pero con mala elección de pivote (por ejemplo, siempre el primero sobre un array ya ordenado) degenera a O(n²). Por eso las implementaciones reales aleatorizan el pivote o usan la mediana de tres.
Algoritmo Peor caso Caso medio Memoria extra ¿Estable?
Burbuja O(n²) O(n²) O(1)
Inserción O(n²) O(n²) O(1)
Selección O(n²) O(n²) O(1) No
Merge sort O(n log n) O(n log n) O(n)
Quicksort O(n²) O(n log n) O(log n) No

Estabilidad: el detalle que sí importa

Un algoritmo es estable si los elementos con la misma clave conservan su orden relativo. Parece un tecnicismo hasta que ordenas dos veces:

// Facturas ya ordenadas por fecha; ahora, por cliente:
facturas.sort((a, b) => a.cliente.localeCompare(b.cliente));
// Estable   → dentro de cada cliente SIGUEN por fecha ✅
// Inestable → el orden por fecha se pierde ❌

Con un algoritmo estable, ordenaciones sucesivas componen: por fecha y luego por cliente = agrupado por cliente y cronológico dentro. Es la forma idiomática de ordenar por múltiples criterios.

Lo que tu lenguaje usa de verdad

Los runtimes no eligen un algoritmo — los combinan:

  • Timsort (Python, Java, V8 para JavaScript): merge sort que detecta tramos ya ordenados (runs) y usa inserción en los pequeños. Con datos del mundo real — que casi nunca vienen en orden aleatorio — vuela.
  • pdqsort / introsort (C++, Rust, Go): quicksort que se autovigila y salta a heapsort si detecta que degenera, e inserción en los tramos cortos.

La lección de diseño es finísima: los algoritmos “de juguete” que acabas de aprender son los ingredientes de los industriales. Inserción vive dentro de Timsort; la idea de mezcla de merge sort, también. Entenderlos no era ejercicio académico — era leer las piezas del motor real.