meskeIA

Simulador de Recursión

Pila de llamadas, árbol recursivo y memoization paso a paso

© 2026 meskeIA© 2026
700 ms

Guía de Recursión

Pila de llamadas, casos base y memoization

Comparativa de Funciones Recursivas

FunciónCaso basePaso recursivoComplejidad
Factorial(n)n ≤ 1 → retorna 1n × factorial(n − 1)O(n) tiempo, O(n) pila
Fibonacci(n)n ≤ 1 → retorna nfib(n − 1) + fib(n − 2)O(2ⁿ) sin memo, O(n) con memo
Torres de Hanoi(n)n = 1 → mover 1 disco2 × hanoi(n − 1) + 1 mov.O(2ⁿ) movimientos, O(n) pila
MCD(a, b)b = 0 → retorna amcd(b, a mod b)O(log min(a, b))
Suma de dígitos(n)n < 10 → retorna n(n mod 10) + suma(n div 10)O(log₁₀ n)
Búsqueda binaria(arr, x)rango vacío → −1; medio = x → índicebuscar en mitad correspondienteO(log n) tiempo y pila

Casos de Uso Reales

Recorrer estructuras de árbol

Sistemas de archivos, árboles DOM, JSON anidados o árboles de decisión: la recursión es natural porque la propia estructura es recursiva.

Cada nodo tiene hijos del mismo tipo → función que se llama a sí misma por hijo.
Algoritmos divide y vencerás

Mergesort, quicksort, búsqueda binaria, FFT: dividen el problema en mitades y combinan los resultados. Modelo recursivo limpio y eficiente.

T(n) = 2·T(n/2) + O(n) → O(n log n) por el teorema maestro.
Backtracking y combinatoria

Sudoku, N reinas, generación de permutaciones, laberintos: prueba una opción, recurre, y si no funciona deshaz y prueba la siguiente.

Patrón: probar → recurrir → deshacer (undo) si fracasa.
Programación dinámica

Mochila, cambio de monedas, distancia de edición: empieza con recursión + memo (top down) y luego optimiza a iterativa (bottom up).

Si la recursión repite subproblemas → memoization es la clave.

Preguntas Frecuentes

¿Qué es el caso base y por qué es obligatorio?

El caso base es la condición que detiene la recursión: cuando se cumple, la función retorna sin volver a llamarse. Sin caso base la función se llama infinitamente y acaba con un error de pila.

Regla de oro: el caso base debe alcanzarse desde cualquier entrada válida.

¿Por qué Fibonacci recursivo "ingenuo" es exponencial?

Cada llamada hace 2 llamadas más (fib(n − 1) y fib(n − 2)), y muchas se repiten. fib(40) realiza más de 200 millones de llamadas. Con memoization caché esos resultados y bajas a O(n).

Activa el toggle "Memoization" en el simulador y compara las cifras: la diferencia es brutal.

¿Qué diferencia hay entre recursión e iteración?

La iteración usa bucles (while/for) y no consume pila adicional. La recursión es más expresiva en problemas que se definen sobre sí mismos (árboles, divide y vencerás) pero gasta memoria de pila. Cualquier recursión se puede transformar a iteración con una pila explícita.

¿Cuándo conviene aplicar memoization?

Cuando hay subproblemas que se repiten con los mismos argumentos. Si cada llamada usa argumentos distintos (caso del factorial), la memoization no aporta nada. En Fibonacci, mochila, distancia de edición → muy útil.

¿Qué es un "stack overflow" en recursión?

Cada llamada ocupa un frame en la pila de ejecución. Si la profundidad supera el límite del runtime (~10 000-20 000 frames en JavaScript), el motor lanza "Maximum call stack size exceeded". Causa típica: recursión sin caso base o entrada muy grande.

¿Existe optimización de tail calls en JavaScript?

La especificación ES2015 incluye Tail Call Optimization (TCO), pero en la práctica solo Safari la implementa. V8 (Chrome, Node) y Firefox no la activan. Por eso, en JavaScript es prudente convertir recursiones profundas a iteración.

En Python pasa igual: no hay TCO. En Scheme o Haskell sí, y son recursivos por diseño.

Cómo Diseñar una Función Recursiva — Paso a Paso

1
Identifica el caso base

¿Cuál es la entrada más simple posible? ¿Qué resultado retorna sin necesidad de recurrir? Sin esto, la función no termina.

2
Define el paso recursivo

Asume que la función ya funciona para una entrada más pequeña. ¿Cómo combinas ese resultado con la entrada actual? Ese es el paso recursivo.

3
Garantiza el avance hacia el caso base

Cada llamada debe acercarse al caso base (n disminuye, rango se reduce…). Si no, stack overflow garantizado.

4
Traza la ejecución mentalmente

Pinta el árbol de llamadas para una entrada pequeña. ¿Coincide con lo esperado? Si no, revisa caso base y paso recursivo.

5
Optimiza si hay subproblemas repetidos

Si el árbol contiene nodos con los mismos argumentos, aplica memoization (cache). Mejora drásticamente la complejidad.

Mejores Prácticas

Define el caso base PRIMERO

Antes de pensar en el paso recursivo, escribe la condición de parada y su retorno. Evita stack overflow desde el primer día.

Asegura el avance

Cada llamada debe trabajar con un argumento estrictamente más simple. Si pasas el mismo argumento, recursión infinita.

Confía en la inducción

No intentes desarrollar mentalmente toda la pila. Asume que la llamada recursiva funciona correctamente para entradas más pequeñas y usa ese resultado.

Memoiza cuando hay solapamiento

Si dibujas el árbol y ves los mismos argumentos en distintos nodos, cachea resultados. Pasas de exponencial a polinómico.

Convierte a iterativo si la pila es profunda

Recursiones con miles de frames son arriesgadas en JavaScript. Una pila explícita + bucle while elimina el riesgo.

Calcula la complejidad

Antes de ejecutar, plantea la ecuación de recurrencia: T(n) = ... Aplica el teorema maestro o expansión de árbol para estimar el coste.

Errores frecuentes al programar recursión
  • Olvidar el caso base: recursión infinita y "Maximum call stack size exceeded".
  • Caso base inalcanzable: existe en el código pero la entrada nunca lo activa (por ejemplo, restar mal el argumento).
  • Modificar variables compartidas: usar variables globales mutables dentro de la recursión rompe la inducción y produce bugs difíciles de detectar.
  • No memoizar Fibonacci o problemas similares: aceptas un coste exponencial cuando podrías tener O(n).
  • Recursión sobre estructuras enormes: recorrer JSON profundamente anidado o árboles desbalanceados puede saturar la pila. Plantéate iterativo.
  • Confundir el orden de retorno: en algunas funciones (ej. construir cadenas) el orden en que combinas el resultado del subproblema cambia el resultado final.

Apps relacionadas