Principiante · lógica

Ordenar tres números

Hay seis órdenes posibles y solo uno es correcto. Puedes escribirlos todos con if anidados — o hacer tres comparar-e-intercambiar y dejar que el orden emerja, el mismo truco que usa toda ordenación real.

En una fraseTres comparar-e-intercambiar: asegura <code>a ≤ b</code>, luego <code>a ≤ c</code>, luego <code>b ≤ c</code>; escribe <code>a b c</code>.

El problema

Entrada: Tres enteros (cada uno −1000 a 1000), separados por espacios. Se permiten valores iguales.

Salida: Los mismos tres números en orden no decreciente, separados por un solo espacio.

Ejemplos:

EntradaSalida
3 1 21 2 3
5 5 11 5 5

Los valores iguales son la prueba que separa la ordenación real de la chapucera: 5 5 1 debe dar 1 5 5, y una cadena con < estricto lo maneja — pero una cadena con el orden mal no.

Tu solución

main.cpp — tu solución
Entrada personalizada para «Ejecutar mi entrada»

La corrección corre en tu navegador contra pruebas ocultas. Un bucle infinito se corta a los 3 segundos — aun así, asegúrate de que todo bucle tenga salida. Tu código se guarda solo mientras escribes.

¿Atascado? Pistas

Pista 1 — Escribe el intercambio una vez y reúsalo

Las mismas tres líneas de Intercambiar dos números aparecen tres veces: if (a > b) { int t = a; a = b; b = t; } y lo mismo para a, c y b, c. Mismo bloque, distinto par.

Pista 2 — Por qué ese orden funciona

Tras la primera comparación a guarda el menor de los a, b originales. Tras la segunda, a tampoco supera a c — así que a es el mínimo global y está resuelto. La tercera comparación solo ordena los dos restantes. Vista la invariante, las tres líneas dejan de parecer arbitrarias.

Pista 3 — La alternativa con if anidados

Puedes enumerar los seis órdenes con if (a <= b && b <= c) ... else if ... y pasará. También son seis ramas que duplican los tres couts — y deja de escalar en cuanto hay un cuarto número. Comparar-e-intercambiar es la versión que crece.

Solución (¡inténtalo primero!)
#include <iostream>
using namespace std;

int main() {
    int a, b, c;
    cin >> a >> b >> c;

    if (a > b) { int t = a; a = b; b = t; }
    if (a > c) { int t = a; a = c; c = t; }
    if (b > c) { int t = b; b = c; c = t; }

    cout << a << " " << b << " " << c << endl;
    return 0;
}

Tres comparar-e-intercambiar es el ordenamiento burbuja con los bucles desenrollados — la versión general está en Ordenamiento burbuja, y ordenar dos arrays que deben seguir emparejados en Fusionar intervalos. El instinto de intercambiar repetidamente en vez de enumerar casos merece conservarse.

Análisis profundo

Por qué funciona

Tres comparar-e-intercambiar en el orden (a,b), (a,c), (b,c) establecen la invariante a ≤ b ≤ c: tras las dos primeras comparaciones a es el mínimo de los tres, así que la tercera solo tiene que ordenar el par restante. Es el burbuja con los bucles desenrollados.

El coste

O(1) — como mucho tres comparaciones y tres intercambios; el problema general necesita O(n²) con burbuja u O(n log n) con una ordenación buena.

Dónde falla

  • Orden de comparaciones equivocado. Hacer (b,c) primero y luego (a,b) deja a sin verificar contra c — el bug clásico de ordenación parcial.
  • Enumerar los seis órdenes con if anidados: correcto pero seis bloques de impresión duplicados que dejan de escalar con un cuarto número.
  • Perder el temporal en el intercambio, con lo que un valor se duplica y otro desaparece.

Siguiente paso

Desenrollar al revés es exactamente Ordenamiento burbuja; ordenar arrays emparejados sin romper la pareja es Fusionar intervalos.

Dos cosas para recordar

  • Tres comparar-e-intercambiar en el orden correcto ordenan tres valores — es el burbuja desenrollado.
  • Tras las dos primeras comparaciones a es el mínimo global, así que la tercera solo ordena el resto.
🐞 Esta versión falla: ábrela y pruébala

Compara (b,c) antes de (a,c) — a nunca se verifica contra el mayor

#include <iostream>
using namespace std;

int main() {
    int a, b, c;
    cin >> a >> b >> c;
    if (b > c) { int t = b; b = c; c = t; }   // bug: wrong order
    if (a > b) { int t = a; a = b; b = t; }
    cout << a << " " << b << " " << c << endl;
    return 0;
}