¿Cuál es la estructura de datos utilizada para realizar la recursividad?

Una pila, generalmente hecha de una lista vinculada, encima de un vector.

Por ejemplo, c, c ++, Pascal y muchos otros lenguajes compilados, funcionan directamente en la pila de la CPU.

  • Lista: cada llamada de función crea un marco de pila, con todas las variables locales, parámetros, dirección de retorno y un puntero al marco de pila anterior (como un nodo en una lista que apunta al nodo anterior).
  • Vector: crece o se reduce dinámicamente. Asigna memoria de forma dinámica, desde el sistema operativo, pero no la devuelve. (Cuando se llama a una función o se inicializa una variable fuera de la pila asignada, el sistema operativo la aumenta).

Nota: con lenguajes de intérprete o lenguajes funcionales profundamente recursivos, puede implementarse de manera ligeramente diferente. Tal vez una lista vinculada, de nodos independientes.

Nota 2: las rutinas y los subprocesos rompen este modelo, cuando puede haber múltiples pilas creadas para cada subproceso, y se eliminan cuando se unen / terminan.

Un montón.

La mejor manera de entender esto sería pensarlo así,

El trabajo que se ha realizado parcialmente en las capas superiores de la recursión se almacena en la pila.

Una vez que se completan los niveles inferiores, la capa que se encuentra sobre ella se abre y se fusiona con el resultado para resolver el nivel inmediato.

Encontrarás cientos de ejemplos de esto en la red.

¡Un montón! Si llama a una función o método de forma recursiva, el compilador usa la pila de llamadas para guardar cada variable de iteración (el estado de la iteración) para que el código pueda continuar desde donde se detuvo cuando se llamó al método recursivo.

Si alguien necesita reescribir un algoritmo recursivo de manera iterativa, este programador ciertamente usará una pila para el mismo propósito.

Apilar. Debido a su propiedad LIFO (último en entrar, primero en salir) recuerda a su ‘llamador’, por lo que sabe a quién devolver cuando la función tiene que regresar. La recursión utiliza la pila del sistema para almacenar las direcciones de retorno de las llamadas a funciones.

Cada función recursiva tiene su función iterativa equivalente (no recursiva). Incluso cuando se escriben tales procedimientos iterativos equivalentes, se debe utilizar la pila explícita.

La recursión se puede implementar de varias maneras. Por lo general, los programadores piensan en términos una rutina que se llama a sí misma y el puntero de la pila utilizado para recurrir y relajarse. Sin embargo, la recursión se puede hacer con solo un contador sin usar una pila o cambiar el puntero de la pila. Algunos idiomas en realidad implementan un pragma que permite una llamada y un valor devuelto sin tocar la pila a medida que el rendimiento aumenta para una recursión profunda, pero el programa debe mantener un contador y saber cuándo finalmente hacer un retorno normal al llamador original. Los mainframes de IBM tienen una llamada de servicio que permite que un programa recursivo no tenga que regresar y desenrollar la recursividad. Es como un goto a través de subrutinas; um tienes que saber qué haces con eso 🙂

Tradicionalmente, uno usa una pila.
La recursividad de la cola se puede hacer con variables estáticas (¿Qué es la recursividad de la cola? Tiene una buena discusión sobre esto).
En una arquitectura de mensajería distribuida, uno puede (a veces) extender la recursión de cola pasando “continuaciones” (cubos completos de estado) entre procesos (o procesadores) junto con una dirección “goto”.

Cada vez que realiza una recursión, cada llamada al método / función crea un marco de llamadas basado en la pila, de modo que después de llegar a un caso base, esa pila comienza a saltar cada llamada al método. Entonces apilar sería la respuesta.

Generalmente se apilan, y hay muchos tipos para su implementación