La recursión es una de las herramientas más elegantes de la programación: una función que se llama a sí misma para resolver instancias progresivamente más pequeñas de un problema. Para recorrer estructuras de árbol — como el sistema de archivos, árboles de categorías o estructuras XML — suele ser la solución más natural y eficiente. Este artículo explica el concepto y lo ilustra con un ejemplo concreto en C#.
Cómo funciona la recursión
La idea subyacente es simple: una función recibe un nodo como parámetro, lo procesa y se llama a sí misma tantas veces como ramas hijas tenga el nodo actual. Las llamadas sucesivas terminan cuando se alcanzan los nodos “hoja” — aquellos sin hijos.
Sin una condición de salida bien definida, la recursión genera un bucle infinito que conduce a un desbordamiento de pila. La función debe, por tanto, llamarse a sí misma únicamente si aún hay datos que procesar.
Ventajas y limitaciones
- Principal ventaja: código compacto y expresivo para navegar por estructuras jerárquicas de profundidad arbitraria.
- Limitación 1: sin una gestión correcta de la condición de salida, genera bucles infinitos.
- Limitación 2: cada llamada añade un marco a la pila. En estructuras muy profundas, el desbordamiento de pila es posible incluso con una lógica correcta.
- Buena práctica: minimizar los datos pasados como parámetros — es preferible pasar referencias o índices antes que copiar objetos enteros.
Ejemplo: exploración recursiva del sistema de archivos en C#
El ejemplo implementa un recorrido recursivo de carpetas del sistema de archivos. La función ReadFolderFiles recibe una carpeta, la recorre y, por cada subcarpeta encontrada, se llama a sí misma de nuevo con la subcarpeta como nuevo parámetro. El algoritmo termina cuando no quedan más subcarpetas por visitar.
using System;
using System.IO;
namespace RecursionOnFS
{
class Class1
{
[STAThread]
static void Main(string[] args)
{
DirectoryInfo d = new DirectoryInfo(@"C:StartingDirectory");
ReadFolderFiles(d);
}
static void ReadFolderFiles(DirectoryInfo pDir)
{
DirectoryInfo[] subd = pDir.GetDirectories();
foreach (DirectoryInfo dd in subd)
{
if (dd.Attributes == FileAttributes.Directory)
{
// Recursive call: descend into the subfolder
ReadFolderFiles(dd);
}
else
{
Console.WriteLine(dd.FullName);
}
}
}
}
}
El mismo patrón se aplica a cualquier estructura jerárquica: árboles de categorías en una base de datos, nodos XML, estructuras JSON anidadas o grafos acíclicos. La clave es siempre la misma — identificar la condición de salida y reducir el problema en cada iteración.
Artículo publicado originalmente en itvirtualcommunity.net (2004), reescrito y actualizado en 2012.







