Saltar al contenido
algoritmos.java · devschool

Algoritmos, pseudocódigo y diagramas de flujo

Lección 2 de 39 · 14 min de lectura · Actualizado el

En esta lección
  1. Qué es un algoritmo
  2. Pseudocódigo
  3. Diagramas de flujo
  4. De pseudocódigo a Java
  5. Ejemplo 1: el mayor de tres números
  6. Comprobar un algoritmo: la traza
  7. Ejemplo 2: el factorial
  8. Ejemplo 3: ¿es primo?
  9. Ejemplo 4: la suma de los dígitos
  10. Cómo descomponer un problema
  11. Errores frecuentes
  12. Resumen

Antes de escribir una sola línea de Java conviene aprender a pensar la solución: decidir qué pasos hay que dar y en qué orden. En esta lección aprenderás qué es un algoritmo, cómo escribirlo en pseudocódigo y en un diagrama de flujo, cómo convertirlo en Java y cómo comprobar a mano que funciona con una traza. Terminarás con cuatro ejemplos clásicos que aparecen en todos los exámenes de programación.

Nota: en esta lección verás código Java con variables, if y bucles que todavía no conoces a fondo. No te preocupes: lo importante ahora es la lógica. Cada instrucción tiene su lección propia más adelante.

Qué es un algoritmo

Un algoritmo es una lista de pasos ordenados, precisos y finitos que resuelve un problema. Una receta de cocina o las instrucciones para montar un mueble son algoritmos.

Cada paso debe ser preciso (“echa un poco de sal” no vale para un ordenador; “echa 5 gramos” sí), el orden importa (no puedes freír el huevo antes de cascarlo) y el algoritmo tiene que terminar en algún momento.

Todo algoritmo tiene tres partes:

ParteQué esEjemplo: calcular el precio con IVA
EntradaLos datos que recibeEl precio sin IVA
ProcesoLas operaciones que haceMultiplicar por 1,21
SalidaEl resultado que devuelveEl precio final

Las tres estructuras básicas

Cualquier algoritmo se construye combinando solo tres bloques: secuencia (pasos uno detrás de otro), decisión (“si llueve, coge el paraguas”) y repetición (“mientras quede ropa en el cesto, tiende una prenda”). En Java se corresponden con instrucciones normales, con las condicionales y con los bucles.

Pseudocódigo

El pseudocódigo es una forma de escribir un algoritmo en lenguaje natural, pero con una estructura parecida a la de un programa. No tiene reglas oficiales; su ventaja es que te deja pensar la solución sin preocuparte de la sintaxis (puntos y coma, llaves, tipos).

Este es el pseudocódigo para calcular el precio de una compra con IVA:

INICIO
    LEER precio
    total ← precio * 1.21
    ESCRIBIR total
FIN

La flecha ← significa asignar: guarda el valor de la derecha en la variable de la izquierda (un nombre que guarda un dato).

Con una decisión, el pseudocódigo para saber si un alumno ha aprobado sería:

INICIO
    LEER nota
    SI nota >= 5 ENTONCES
        ESCRIBIR "Aprobado"
    SINO
        ESCRIBIR "Suspenso"
    FIN SI
FIN

La sangría (lo de dentro del SI va desplazado) muestra de un vistazo qué pasos dependen de la condición.

Diagramas de flujo

Un diagrama de flujo representa el algoritmo con dibujos unidos por flechas. Cada forma tiene un significado:

FormaUso
ÓvaloInicio y fin
ParalelogramoEntrada o salida de datos (leer, escribir)
RectánguloProceso: un cálculo o una asignación
RomboDecisión: una pregunta con dos salidas, sí y no
FlechasEl orden en que se recorren los pasos

El algoritmo del aprobado, dibujado con texto, quedaría así:

        ( INICIO )
            |
            v
      / LEER nota /
            |
            v
     < ¿nota >= 5? >
       |         |
      sí         no
       |         |
       v         v
/ "Aprobado" / / "Suspenso" /
       |         |
       +----+----+
            |
            v
         ( FIN )

Un bucle se dibuja como una flecha que vuelve hacia atrás hasta un rombo. Los diagramas son muy visuales para algoritmos cortos, pero con algoritmos largos se vuelven enormes; por eso en la práctica se usa más el pseudocódigo. En FP es habitual que te pidan los dos.

Consejo: para dibujarlos basta papel y lápiz o una herramienta gratuita como draw.io. En un examen cuenta que las formas sean las correctas y que ningún camino quede sin terminar.

De pseudocódigo a Java

Pasar un pseudocódigo bien escrito a Java es casi una traducción palabra por palabra:

PseudocódigoSignificadoJava
x ← 5Guardar un valorint x = 5; o x = 5;
ESCRIBIR xMostrar por pantallaSystem.out.println(x);
LEER xPedir un datoUn Scanner
SI ... ENTONCES ... SINO ... FIN SIDecisiónif (...) { } else { }
MIENTRAS ... HACER ... FIN MIENTRASRepetir mientras se cumplawhile (...) { }
PARA i DESDE 1 HASTA nRepetir n vecesfor (int i = 1; i <= n; i++) { }

Para no complicar los ejemplos, los datos de entrada irán escritos directamente en el código.

Ejemplo 1: el mayor de tres números

Problema: dados tres números, mostrar el mayor.

La idea: supón que el primero es el mayor y compáralo con los otros dos. Si alguno es mayor, pasa a ser el nuevo “mayor”.

INICIO
    LEER a, b, c
    mayor ← a
    SI b > mayor ENTONCES
        mayor ← b
    FIN SI
    SI c > mayor ENTONCES
        mayor ← c
    FIN SI
    ESCRIBIR mayor
FIN

En Java:

public class MayorDeTres {
    public static void main(String[] args) {
        int a = 14;
        int b = 31;
        int c = 27;

        int mayor = a;
        if (b > mayor) {
            mayor = b;
        }
        if (c > mayor) {
            mayor = c;
        }
        System.out.println("El mayor es " + mayor);
    }
}
// El mayor es 31

Frente a la típica cadena de if (a > b && a > c)..., esta idea escala: con un bucle sirve para el mayor de cualquier cantidad de números, como verás en arrays.

Comprobar un algoritmo: la traza

Una traza (o prueba de escritorio) consiste en ejecutar el algoritmo a mano, paso a paso, apuntando en una tabla el valor de cada variable. Es la mejor forma de encontrar fallos.

La traza del mayor de tres con a = 14, b = 31, c = 27:

PasoInstrucciónmayorComentario
1mayor ← a14
2¿b > mayor? → ¿31 > 14?14Sí, entra
3mayor ← b31
4¿c > mayor? → ¿27 > 31?31No, no entra
5ESCRIBIR mayor31Sale 31

Haz siempre trazas con varios casos, incluidos los raros: el mayor en primera o última posición, dos iguales, negativos…

Consejo: en los exámenes es habitual que te den un trozo de código y te pregunten qué muestra. La traza en una tabla es la forma de responder sin equivocarte.

Ejemplo 2: el factorial

Problema: calcular el factorial de un número n, que es el producto de todos los enteros desde 1 hasta n. Se escribe n!. Por ejemplo, 5! = 1 × 2 × 3 × 4 × 5 = 120.

Aquí hace falta un acumulador: una variable que empieza con un valor neutro y a la que en cada vuelta del bucle se le “añade” algo. Para multiplicar, el valor neutro es 1 (si empezaras en 0, todo daría 0).

En pseudocódigo: resultado ← 1 y luego PARA i DESDE 2 HASTA n HACER resultado ← resultado * i. En Java:

public class Factorial {
    public static void main(String[] args) {
        int n = 5;
        long resultado = 1;
        for (int i = 2; i <= n; i++) {
            resultado = resultado * i;
        }
        System.out.println(n + "! = " + resultado);
    }
}
// 5! = 120

La traza con n = 5:

Vueltairesultado antesresultado después
1212
2326
34624
4524120
—6—Sale del bucle: 6 no es <= 5

Usamos long porque el factorial crece muy deprisa (13! ya no cabe en un int). Con n = 0 el bucle no da ninguna vuelta y sale 1, que es correcto. También se puede calcular con recursividad.

Ejemplo 3: ¿es primo?

Problema: saber si un número es primo, es decir, si solo se puede dividir de forma exacta entre 1 y él mismo. El 7 es primo; el 9 no, porque 9 entre 3 da exacto.

La idea: prueba a dividir entre 2, 3, 4… Si alguna división es exacta, no es primo. Y no hace falta llegar hasta n - 1: si n tiene un divisor mayor que su raíz cuadrada, tiene otro menor, así que basta con probar mientras d × d <= n. Para 91 solo hay que probar hasta 9, no hasta 90.

Para saber si una división es exacta se usa el resto: en Java, el operador % (en pseudocódigo suele escribirse MOD). Lo escribimos como un método que devuelve true o false (los verás en métodos); en cuanto encuentra un divisor, return false termina sin seguir probando:

public class Primo {
    static boolean esPrimo(int n) {
        if (n < 2) {
            return false;
        }
        for (int d = 2; d * d <= n; d++) {
            if (n % d == 0) {
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        System.out.println(esPrimo(29));
        System.out.println(esPrimo(91));
        System.out.println(esPrimo(1));
    }
}
// true
// false
// false

La traza de esPrimo(91):

dd * d <= 9191 % dQué pasa
24, sí1Sigue
39, sí1Sigue
416, sí3Sigue
525, sí1Sigue
636, sí1Sigue
749, sí0Divisor encontrado: devuelve false

91 parece primo, pero es 7 × 13: no te fíes de la intuición.

Ejemplo 4: la suma de los dígitos

Problema: sumar las cifras de un número. Para 4073, el resultado es 4 + 0 + 7 + 3 = 14.

El truco está en dos operaciones con el número 10:

  • numero % 10 da la última cifra (el resto de dividir entre 10): 4073 % 10 = 3.
  • numero / 10 quita la última cifra (división entera, sin decimales): 4073 / 10 = 407.

Repetimos (MIENTRAS numero > 0) hasta que el número se quede en 0:

public class SumaDigitos {
    public static void main(String[] args) {
        int numero = 4073;
        int suma = 0;
        while (numero > 0) {
            int ultimo = numero % 10;
            suma = suma + ultimo;
            numero = numero / 10;
        }
        System.out.println("Suma de dígitos: " + suma);
    }
}
// Suma de dígitos: 14
Vueltanumero al empezarultimosumanumero al terminar
1407333407
240771040
3400104
444140

Con el mismo esquema puedes contar cifras, invertir un número (4073 → 3704) o comprobar si es capicúa.

Cómo descomponer un problema

Para los ejercicios largos se usa el diseño descendente: partir el problema en subproblemas, y estos en otros más pequeños, hasta que cada uno sea fácil.

Imagina este enunciado: “Tenemos los minutos que ha entrenado una persona en el gimnasio cada día de la semana (0 si no fue). Muestra cuántos días entrenó, la media de minutos por sesión y el día en que más entrenó.”

Antes de programar, descompón:

Informe semanal del gimnasio
├── Contar días entrenados   → recorrer y contar los que son > 0
├── Media por sesión         → sumar todo y dividir entre los días entrenados
│                               (¡cuidado si son 0!)
└── Mejor día                → buscar la posición del máximo
                                y traducirla a nombre (0 = lunes...)

Cada rama es un problema pequeño que ya sabes resolver. En Java, cada una se convierte en un método con un nombre claro:

public class Gimnasio {
    public static void main(String[] args) {
        int[] minutos = {45, 0, 60, 30, 0, 90, 20};
        System.out.println("Días entrenados: " + contarDiasActivos(minutos));
        System.out.println("Media por sesión: " + mediaSesion(minutos) + " min");
    }

    static int contarDiasActivos(int[] minutos) {
        int dias = 0;
        for (int m : minutos) {
            if (m > 0) {
                dias++;
            }
        }
        return dias;
    }

    static double mediaSesion(int[] minutos) {
        int total = 0;
        for (int m : minutos) {
            total += m;
        }
        int dias = contarDiasActivos(minutos);
        return dias == 0 ? 0 : (double) total / dias;
    }
}
// Días entrenados: 5
// Media por sesión: 49.0 min

El tercer método, mejorDia, es el máximo de arrays guardando la posición; inténtalo tú. Cada parte se prueba por separado (si la media sale mal, sabes en qué método mirar), se reutiliza (mediaSesion aprovecha contarDiasActivos) y el main se lee como el enunciado.

Una receta para cualquier ejercicio

  1. Entiende el enunciado: entradas, salida esperada y un ejemplo resuelto a mano.
  2. Busca los casos especiales: cero, negativos, listas vacías, repetidos.
  3. Descompón y escribe el pseudocódigo de cada parte.
  4. Haz la traza con tu ejemplo y con los casos especiales.
  5. Traduce a Java y ejecuta. Si el resultado no coincide con tu traza, el error está en la traducción; si coincide pero es incorrecto, está en el algoritmo.

Errores frecuentes

  • Iniciar mal los acumuladores. Una suma empieza en 0; un producto, en 1; un máximo, en el primer valor (no en 0, que falla con números negativos).
  • Olvidar que la variable del bucle tiene que cambiar. Si en un MIENTRAS nunca actualizas la condición (numero ← numero / 10), el bucle no termina.
  • Probar solo con el ejemplo del enunciado. Haz trazas con casos límite: 0, 1, negativos, valores iguales.
  • Diagramas con caminos sin cerrar. Cada rombo tiene dos salidas y las dos deben llegar a algún sitio.

Resumen

ConceptoQué es
AlgoritmoPasos precisos, ordenados y finitos que resuelven un problema
Secuencia, decisión, repeticiónLas tres estructuras con las que se construye cualquier algoritmo
PseudocódigoEl algoritmo en lenguaje natural estructurado, sin sintaxis de ningún lenguaje
Diagrama de flujoEl algoritmo dibujado: óvalos, paralelogramos, rectángulos, rombos y flechas
TrazaEjecutar el algoritmo a mano anotando las variables en una tabla
AcumuladorVariable que va sumando (empieza en 0) o multiplicando (empieza en 1)
% 10 y / 10Sacar y quitar la última cifra de un número
Diseño descendentePartir un problema grande en subproblemas pequeños

Ya sabes pensar un algoritmo. Para escribirlo en Java necesitas guardar datos: empieza por variables y tipos.

Pon a prueba lo que has aprendido

[Java] ¿Con qué valor hay que inicializar un acumulador que va a multiplicar, como en el factorial?

[Java] ¿Qué imprime este programa?
int n = 1250;
int inv = 0;
while (n > 0) {
    inv = inv * 10 + n % 10;
    n = n / 10;
}
System.out.println(inv);

[Java] En esPrimo, el bucle es for (int d = 2; d * d <= n; d++). ¿Por qué basta con probar hasta que d * d supere a n?

[Java] ¿Para qué sirve hacer una traza de un algoritmo?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.