Recursividad en Java
Nivel 2 · 30 min · 3 preguntas

Antes y despues de la llamada

Lo que pasa al bajar no es lo que pasa al subir.

La idea en una frase

El codigo antes de la llamada corre mientras la pila crece; el de despues corre al reves, mientras se vacia.

Antes de ver codigo

Es como entrar y salir de una serie de habitaciones. Al entrar prendes la luz de cada una, en orden. Al salir las vas apagando, pero forzosamente en orden inverso, porque para salir de la primera antes tienes que haber salido de todas las de adentro.

Dos momentos, no uno

Toda llamada recursiva parte el metodo en dos mitades. El codigo que esta antes de la llamada se ejecuta mientras la pila crece. El que esta despues se ejecuta mientras la pila se vacia, en orden inverso.

Este es el punto donde se atasca la mayoria. Cambiar una linea de lugar invierte el resultado completo.

static void bajando(int n) {
    if (n == 0) return;
    System.out.print(n + " ");   // ANTES
    bajando(n - 1);
}
// bajando(5)  ->  5 4 3 2 1

static void subiendo(int n) {
    if (n == 0) return;
    subiendo(n - 1);
    System.out.print(n + " ");   // DESPUES
}
// subiendo(5)  ->  1 2 3 4 5

Mismo metodo, misma condicion, mismo decremento. Solo cambio el orden de dos lineas y la salida se invirtio.

Por que se invierte

En subiendo(5), ninguna impresion ocurre hasta que la pila llega al fondo. Los cinco marcos quedan congelados justo antes de su print. Cuando el caso base retorna, se descongelan de arriba hacia abajo: primero el del 1, luego el del 2, y asi.

Regla practica: lo que escribes despues de la llamada recursiva sale al reves.

StackOverflowError

La pila tiene un tamano fijo, tipicamente 512 KB o 1 MB. Cuando se llena, la JVM lanza StackOverflowError. No es una excepcion normal: es un Error, y significa que agotaste memoria de pila, no memoria del heap.

En un metodo simple suele reventar entre 10.000 y 20.000 llamadas, pero depende del tamano de cada marco. Se puede ampliar con el flag -Xss4m, aunque eso casi siempre es tapar el sintoma.

Ejecuta y observa

Aqui es donde la teoria de arriba se vuelve concreta. Cambia los parametros, dale a Reproducir, y sobre todo usa las flechas para ir paso a paso: la velocidad automatica sirve para ver la forma general, pero lo que de verdad ensena es detenerse en un retorno y entender por que vuelve ahi y no a otro lado.

Errores que vas a cometer

No son ejemplos inventados: son los que aparecen una y otra vez en los parciales. Lee el codigo, decide tu mismo que esta mal, y solo despues abre la correccion. Si la abres de una, no aprendes nada.

Poner la impresion del lado equivocado

// Quiero imprimir 1..n en orden
static void contar(int n) {
    if (n == 0) return;
    System.out.print(n + " ");
    contar(n - 1);
}

Comprueba lo que entendiste

Responde sin devolverte a leer. Si fallas no pasa nada: la explicacion te dice exactamente donde estaba el hueco, y ese es el momento en que de verdad se aprende. Con el 70% el nivel queda aprobado.