📊 ¿Qué es un diagrama de flujo?
Un diagrama de flujo (en inglés, flowchart) es una representación gráfica de un algoritmo que utiliza símbolos estandarizados conectados por flechas para describir el flujo de ejecución de un programa. Cada símbolo representa una acción específica —un cálculo, una decisión, una entrada de datos— y las flechas indican el orden en que se ejecutan.
La potencia del diagrama de flujo reside en su capacidad para hacer visible lo invisible: la lógica de un programa. Antes de escribir una sola línea de código, el programador puede dibujar el flujo completo de su algoritmo, detectar errores de lógica, y comunicar su diseño a otros miembros del equipo sin necesidad de conocer un lenguaje de programación concreto.
Los diagramas de flujo son especialmente útiles en las etapas iniciales del aprendizaje de la programación, porque obligan al estudiante a pensar en la lógica del algoritmo de forma independiente al lenguaje. Un diagrama de flujo bien diseñado se puede traducir a Java, Python, C o cualquier otro lenguaje con la misma facilidad.
📜 Breve historia de los diagramas de flujo
Los diagramas de flujo tienen una historia más larga de lo que muchos imaginan. En 1921, el ingeniero industrial Frank Gilbreth presentó ante la Sociedad Americana de Ingenieros Mecánicos (ASME) el concepto de «gráfico de procesos» (process chart), un sistema de símbolos para documentar flujos de trabajo en fábricas.
En la década de 1940, Herman Goldstine y John von Neumann adaptaron estos diagramas para representar programas informáticos, creando lo que hoy conocemos como diagramas de flujo de programación. En 1970, la Organización Internacional de Normalización (ISO) publicó la norma ISO 5807, que estandarizó los símbolos utilizados en los diagramas de flujo y que sigue vigente hasta hoy.
🔷 Símbolos fundamentales
Los diagramas de flujo utilizan un conjunto de símbolos estandarizados según la norma ISO 5807. Cada forma geométrica tiene un significado preciso e inconfundible. Conocer estos símbolos es el primer paso para poder leer y crear diagramas de flujo.
| Símbolo | Nombre | Descripción | Equivalente en Java |
|---|---|---|---|
| Terminal (Inicio/Fin) | Indica el comienzo o el final del diagrama. Todo diagrama tiene exactamente un inicio y al menos un fin | public static void main / fin de main |
|
| Proceso | Representa una acción, cálculo o asignación. Puede agrupar varias operaciones relacionadas | int suma = a + b; |
|
| Decisión | Punto de bifurcación donde se evalúa una condición. Tiene dos salidas: Sí y No (o Verdadero/Falso) | if (a > b) { ... } |
|
| Entrada / Salida | Operación de lectura (teclado, fichero) o escritura (pantalla, impresora) | Scanner.nextInt() / System.out.println() |
|
| Línea de flujo | Flecha que conecta símbolos e indica la dirección de ejecución del programa (normalmente de arriba a abajo) | Orden secuencial de las instrucciones | |
| Conector | Enlaza dos partes del diagrama cuando no caben en la misma página. Se etiqueta con una letra o número | — |
Símbolos basados en la norma ISO 5807. Estilo visual inspirado en los SVGs de DevinCook (Wikimedia Commons, CC BY-SA 4.0).
📐 Reglas de construcción
Construir un diagrama de flujo correcto no es simplemente dibujar cajas y flechas. Existen reglas formales que garantizan que el diagrama sea legible, consistente y pueda traducirse a código sin ambigüedades.
| # | Regla | Motivo |
|---|---|---|
| 1 | Todo diagrama tiene un solo inicio y al menos un fin | Garantiza un punto de entrada único y que el programa siempre termina |
| 2 | El flujo general va de arriba hacia abajo y de izquierda a derecha | Facilita la lectura natural del diagrama |
| 3 | Todas las líneas de flujo deben tener flechas indicando la dirección | Elimina ambigüedad sobre el orden de ejecución |
| 4 | Un rombo de decisión tiene exactamente dos salidas etiquetadas (Sí/No) | Toda condición lógica tiene solo dos resultados posibles |
| 5 | No deben quedar líneas sin conectar (extremos sueltos) | Evita caminos de ejecución sin destino |
| 6 | Las acciones dentro de un proceso deben escribirse con verbos en infinitivo o como asignaciones | Claridad: «Leer N», «Calcular suma», «suma = a + b» |
| 7 | No se cruzan líneas de flujo. Si es inevitable, se usan conectores | Legibilidad del diagrama |
🟢 Ejemplo 1: flujo secuencial (sin decisiones)
El diagrama más sencillo posible: un flujo lineal sin bifurcaciones. El programa lee dos números, calcula su suma y muestra el resultado. Todas las instrucciones se ejecutan una tras otra, sin condiciones ni bucles.
🔹 Pseudocódigo
INICIO Leer A Leer B suma ← A + B Escribir suma FIN
🔹 Diagrama de flujo
🔹 Traducción a Java
import java.util.Scanner; public class SumaDosNumeros { public static void main(String[] args) { Scanner teclado = new Scanner(System.in); System.out.print("Introduce A: "); int a = teclado.nextInt(); // ← Leer A System.out.print("Introduce B: "); int b = teclado.nextInt(); // ← Leer B int suma = a + b; // ← Proceso System.out.println("Suma: " + suma); // ← Escribir teclado.close(); } }
$ java SumaDosNumeros
Introduce A: 7
Introduce B: 3
Suma: 10
🔶 Ejemplo 2: flujo con decisión (if/else)
El verdadero poder de los diagramas de flujo aparece con las decisiones. El programa lee la edad de una persona y determina si es mayor o menor de edad. El rombo de decisión bifurca el flujo en dos caminos posibles.
🔹 Pseudocódigo
INICIO Leer edad SI edad >= 18 ENTONCES Escribir "Mayor de edad" SINO Escribir "Menor de edad" FIN SI FIN
🔹 Diagrama de flujo
🔹 Traducción a Java
import java.util.Scanner; public class MayoriaEdad { public static void main(String[] args) { Scanner teclado = new Scanner(System.in); System.out.print("Introduce tu edad: "); int edad = teclado.nextInt(); if (edad >= 18) { System.out.println("Mayor de edad"); } else { System.out.println("Menor de edad"); } teclado.close(); } }
🔁 Ejemplo 3: flujo con bucle (while)
Los bucles son la estructura que permite repetir un conjunto de instrucciones mientras se cumpla una condición. En un diagrama de flujo, un bucle se reconoce porque una flecha vuelve hacia atrás, creándo un ciclo visual. El programa siguiente suma los números del 1 al N introducido por el usuario.
🔹 Diagrama de flujo
🔹 Traducción a Java
import java.util.Scanner; public class SumaHastaN { public static void main(String[] args) { Scanner teclado = new Scanner(System.in); System.out.print("Introduce N: "); int n = teclado.nextInt(); int i = 1; int suma = 0; while (i <= n) { // ← Rombo de decisión suma = suma + i; // ← Proceso 1 i = i + 1; // ← Proceso 2 (avance) } // ← Flecha de retorno System.out.println("La suma de 1 a " + n + " es: " + suma); teclado.close(); } }
$ java SumaHastaN
Introduce N: 5
La suma de 1 a 5 es: 15
while.💡 Ejemplo 4: el clásico diagrama de la lámpara
Uno de los diagramas de flujo más conocidos del mundo es el de la lámpara que no funciona, creado por Wapcaplet para Wikimedia Commons. Este ejemplo, aparentemente trivial, muestra cómo los diagramas de flujo pueden representar cualquier proceso de toma de decisiones, no solo algoritmos matemáticos.
Diagrama de flujo de la lámpara. Fuente: Wikimedia Commons — GFDL / CC BY-SA.
El diagrama de la lámpara es un ejemplo perfecto de diagrama de flujo de diagnóstico: una secuencia de preguntas (rombos de decisión) que guían al usuario hacia la solución del problema. En programación, esta misma lógica se traduce en una serie de if/else anidados o en un patrón de troubleshooting muy utilizado en soporte técnico.
🔹 Traducción a Java del diagrama de la lámpara
import java.util.Scanner; public class DiagnosticoLampara { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.println("=== Diagnóstico de lámpara ==="); System.out.print("¿La lámpara está enchufada? (s/n): "); if (sc.nextLine().equalsIgnoreCase("n")) { System.out.println("→ Enchufa la lámpara."); } else { System.out.print("¿La bombilla está fundida? (s/n): "); if (sc.nextLine().equalsIgnoreCase("s")) { System.out.println("→ Cambia la bombilla."); } else { System.out.println("→ Repara la lámpara (problema eléctrico)."); } } sc.close(); } }
🔄 De diagrama de flujo a código Java
La traducción de un diagrama de flujo a código Java sigue una correspondencia directa entre símbolos y estructuras del lenguaje. Dominar esta correspondencia es la clave para pasar del diseño visual a la implementación real.
| Símbolo del diagrama | Estructura en Java | Ejemplo |
|---|---|---|
| Terminal (INICIO) | public static void main(String[] args) { | Punto de entrada |
| E/S → Leer | Scanner.nextInt(), Scanner.nextLine() | int n = sc.nextInt(); |
| Proceso | Asignación o cálculo | suma = a + b; |
| Decisión (Sí/No) | if (condicion) { ... } else { ... } | if (edad >= 18) |
| Bucle (flecha de retorno) | while (condicion) { ... } | while (i <= n) |
| E/S → Escribir | System.out.println() | System.out.println(suma); |
| Terminal (FIN) | } (cierre del main) | Fin del programa |
if/else.🔹 Ejemplo completo: ecuación de segundo grado
El siguiente ejemplo, inspirado en el clásico diagrama de flujo de la ecuación de segundo grado de Wikimedia Commons, calcula las raíces de ax² + bx + c = 0 evaluando el discriminante:
import java.util.Scanner; public class Ecuacion2doGrado { public static void main(String[] args) { Scanner sc = new Scanner(System.in); System.out.print("Coeficiente a: "); double a = sc.nextDouble(); System.out.print("Coeficiente b: "); double b = sc.nextDouble(); System.out.print("Coeficiente c: "); double c = sc.nextDouble(); double discriminante = b * b - 4 * a * c; if (discriminante > 0) { double x1 = (-b + Math.sqrt(discriminante)) / (2 * a); double x2 = (-b - Math.sqrt(discriminante)) / (2 * a); System.out.println("Dos raíces reales: x1=" + x1 + ", x2=" + x2); } else if (discriminante == 0) { double x = -b / (2 * a); System.out.println("Raíz doble: x=" + x); } else { System.out.println("No tiene raíces reales (discriminante negativo)"); } sc.close(); } }
$ java Ecuacion2doGrado
Coeficiente a: 1
Coeficiente b: -5
Coeficiente c: 6
Dos raíces reales: x1=3.0, x2=2.0
⚠️ Errores frecuentes de principiante
❌ Error 1: Olvidar etiquetar las salidas del rombo
// INCORRECTO: Rombo de decisión sin «Sí» y «No» en las flechas // El lector no sabe cuál es el camino verdadero y cuál el falso. // CORRECTO: Siempre etiquetar AMBAS salidas del rombo: // Salida izquierda/abajo → Sí (condición verdadera) // Salida derecha/abajo → No (condición falsa)
❌ Error 2: Dejar líneas de flujo sin flecha
// INCORRECTO: Líneas que conectan símbolos sin punta de flecha // No se puede determinar la dirección del flujo. // CORRECTO: TODA línea de flujo lleva flecha indicando // la dirección de ejecución (generalmente de arriba a abajo).
❌ Error 3: Escribir código dentro de los símbolos
// INCORRECTO: Dentro de un rectángulo escribir: // «System.out.println(resultado);» // CORRECTO: Usar lenguaje natural o pseudocódigo: // «Escribir resultado» o «Mostrar resultado» // El diagrama debe ser independiente del lenguaje de programación.
❌ Error 4: Bucle sin condición de salida
// INCORRECTO: Un bucle cuya condición nunca cambia a falso // → Bucle infinito. El programa nunca llega al símbolo FIN. // CORRECTO: Dentro del bucle debe existir una instrucción // que eventualmente haga la condición falsa (p.ej. i = i + 1). // Es el equivalente a «olvidar el i++ en un for de Java».
✏️ Ejercicios prácticos
Ejercicio 1: Diagrama del número par o impar
Dibuja el diagrama de flujo (o escríbelo en pseudocódigo) de un programa que lea un número entero e imprima si es par o impar. Luego tradúcelo a Java.
Ejercicio 2: Factorial con bucle
Escribe el pseudocódigo y el código Java de un programa que lea un número N y calcule su factorial (N! = 1 × 2 × 3 × ... × N) usando un bucle while. Describe cómo sería el diagrama de flujo correspondiente.
Ejercicio 3: Número mayor de tres
Diseña un diagrama de flujo (en pseudocódigo o descripción) y su traducción a Java para un programa que lea tres números y determine cuál es el mayor de los tres. Pista: necesitarás dos rombos de decisión anidados.