Está en la página 1de 16

Recursividad.

Definición.

Procedimientos recursivos.

Mecánica de recursión.

Transformación de algoritmos recursivos a iterativos.

Recursividad en el diseño.

Complejidad de los algoritmos recursivos.

Ejemplos de casos recursivos


Para entender la recursividad, debes
entender la recursividad
Recursión
La recursión es un concepto amplio, difícil de precisar. Aparece en numerosas
actividades de la vida diaria, por ejemplo, en una fotografía de una fotografía. Otro
caso muy ilustrativo de recursión es el que se presenta en los programas de televisión
en los cuales un periodista transfiere el control a otro periodista que se encuentra en
otra ciudad, y éste hace lo propio con un tercero.

La recursión permite definir un objeto (problemas, estructuras de datos) en términos


de sí mismo. Casos típicos de estructuras de datos definidas de manera recursiva son
los árboles y las listas ligadas.
Recurrencia, recursión o recursividad 
Es la forma en la cual se especifica un proceso basado en su propia definición. Siendo
un poco más precisos, y para evitar el aparente círculo sin fin en esta definición:

Un problema que pueda ser definido en función de su tamaño, sea este N, pueda ser
dividido en instancias más pequeñas (< N) del mismo problema y se conozca la
solución explícita a las instancias más simples, lo que se conoce como casos base, se
puede aplicar inducción sobre las llamadas más pequeñas y suponer que estas
quedan resueltas.

Fuente: Wikipedia

Un subprograma que se llama a sí mismo se dice que es recursivo.


Consideraciones sobre procedimientos recursivos

Condiciones de limitación. Debe designar un procedimiento


recursivo para probar al menos una condición que pueda poner
fin a la recursividad; también debe supervisar los casos en los
que no se satisface ninguna condición dentro de un número
razonable de llamadas recursivas. Si no existe al menos una
condición que pueda cumplirse sin errores, el procedimiento
corre un riesgo elevado de ejecutarse en un bucle infinito.

Uso de la memoria. La aplicación tiene una cantidad de espacio


limitada para las variables locales. Cada vez que un
procedimiento se llama a sí mismo, utiliza más cantidad de ese
espacio para las copias adicionales de sus variables locales. Si
este proceso continúa indefinidamente, se acaba produciendo
un error Stack Overflow Exception?.
Consideraciones de la recursividad

• Los parámetros y variables locales toman nuevos


valores en cada llamada (no se trabaja con los
anteriores).

• Cada vez que se llama un método, el valor de los


parámetros y variables locales se almacenan en la pila
de ejecución. Cuando termina la ejecución se recuperan
los valores de la activación anterior.

• El espacio necesario para almacenar los valores en


memoria (pila) crece en función de las llamadas.
Consideraciones de la recursividad

• Con cada llamada recursiva se crea una copia de


todas las variables y constantes que estén vigentes, y
se guarda esa copia en la pila.

• Además se guarda una referencia a la siguiente


instrucción a ejecutar.

• Al regresar se toma la imagen guardada (registro de


activación) en el tope de la pila y se continúa
operando. Esta acción se repite hasta que la pila
quede vacía.
Eficacia. Casi siempre se puede sustituir un bucle por la recursividad. Un
bucle no tiene la sobrecarga de transferir argumentos, inicializar el
almacenamiento adicional y devolver valores. Su rendimiento puede ser
mucho mayor sin llamadas recursivas.

Recursividad mutua. Si dos procedimientos se llaman mutuamente, el


rendimiento puede ser muy deficiente o incluso puede producirse un bucle
infinito. Este tipo de diseño presenta los mismos problemas que un
procedimiento recursivo único, pero puede ser más difícil de detectar y
depurar.

Llamadas con paréntesis. Cuando un procedimiento se llama a sí mismo de


manera recursiva, debe agregar paréntesis detrás del nombre del
procedimiento, aun cuando no exista una lista de argumentos. De lo
contrario, se considerará que el nombre de la función representa al valor
devuelto por ésta.

Pruebas Si escribe un procedimiento recursivo, debe probarlo


minuciosamente para asegurarse de que siempre cumple ciertas
condiciones de limitación. También debería comprobar que la memoria no
resulta insuficiente debido a la gran cantidad de llamadas recursivas.
MECANICA DE RECURSION.

Es mucho mas difícil desarrollar una solución recursiva para


resolver un problema especifico cuando no se tiene un algoritmo.
No es solo el programa sino las definiciones originales y los
algoritmos los que deben desarrollarse. En general, cuando
encaramos la tarea de escribir un programa para resolver un
problema no hay razón para buscar una solución recursiva. La
mayoría de los problemas pueden resolverse de una manera
directa usando métodos no recursivos. Sin embargo, otros pueden
resolverse de una manera mas lógica y elegante mediante la
recursión.
El factor es, probablemente, un ejemplo fundamental de un problema que
no debe resolverse de manera recursiva, dado que su solución iterativa es
directa y simple. Sin embargo, examinaremos los elementos que permiten
dar una solución recursiva.

Antes que nada, puede reconocerse un gran número de casos distintos que
se deben resolver. Es decir, quiere escribirse un programa para calcular 0!,
1!, 2! Y así sucesivamente. Puede identificarse un caso “trivial” para el cual
la solución no recursiva pueda obtenerse en forma directa. Es el caso de 0!,
que se define como 1. El siguiente paso es encontrar un método para
resolver un caso “complejo” en términos de uno mas “simple”, lo cual
permite la reducción de un problema complejo a uno mas simple. La
transformación del caso complejo al simple resultaría al final en el caso
trivial. Esto significaría que el caso complejo se define, en lo fundamental,
en términos del mas simple.
Examinaremos que significa lo anterior cuando se aplica la función factorial. 4! Es un
caso mas complejo que 3!. La transformación que se aplica al numero para obtener 3
es sencillamente restar 1. Si restamos 1 de 4 de manera sucesiva llegamos a 0, que es
el caso trivial. Así, si se puede definir 4! en términos de 3! y, en general, n! en
términos de (n – 1)!, se podrá calcular 4! mediante la definición de n! en términos de
(n – 1)! al trabajar, primero hasta llegar a 0! y luego al regresar a 4!. En el caso de la
función factorial se tiene una definición de ese tipo, dado que:

n! = n * (n – 1)! Asi, 4! = 4 * 3! = 4 * 3 * 2! = 4 * 3 * 2 * 1! = 4 * 3 * 2 * 1 * 0! = 4 * 3 *
2 * 1 = 24

Estos son los ingredientes esenciales de una rutina recursiva: poder definir un caso
“complejo” en términos de uno más “simple” y tener un caso “trivial” (no recursivo)
que pueda resolverse de manera directa. Al hacerlo, puede desarrollarse una
solución si se supone que se ha resuelto el caso más simple. La función factorial
supone que esta definido (n –1)! y usa esa cantidad al calcular n!.
Procedimientos recursivos

Un procedimiento recursivo es aquél que se llama a sí


mismo.

Public static int factorial(int n)


{
If (n <= 1)
return 1;
else
return n * factorial(n – 1);
}
Ejemplo de Recursividad

Un ejemplo clásico donde se presenta la recursividad es en la definición de un


factorial: El factorial de N es la multiplicación de N por el Factorial de N-1. Sea eso:

Factorial(N) = N * Factorial(N-1) Nótese que la definición de la función se realiza en


base a si misma. Para que la ejecución de este código sea posible, es necesario definir
un caso base, en el caso del factorial seria: Factorial(0) = 1.

De este modo se tiene que:

Factorial(N) = IF(N==0) 1 ELSE N*Factorial(N-1)


Con respecto al ejemplo de la función de Fibonacci:

Se definieron dos casos triviales:

fib(0) = 0 y fib(1) = 1.

Un caso complejo fib(n) se reduce entonces a dos más simples:

fib(n –1) y fib(n –2).

Esto se debe a la definición de fib(n) como fib(n –1) + fib(n – 2), donde
se requiere de dos casos triviales definidos de manera directa. Fib(1) no
puede definirse como fib(0) + fib(−1) porque la función de Fibonacci no
está definida para números negativos.
Tipos de recursión
Recursividad simple
Aquella en cuya definición sólo aparece una llamada recursiva. Se puede
transformar con facilidad en algoritmos iterativos.

Recursividad múltiple
Se da cuando hay más de una llamada a sí misma dentro del cuerpo de la
función, resultando más difícil de hacer de forma iterativa. Un ejemplo típico es
la función de fibonacci

Recursividad anidada
En algunos de los argumentos de la llamada recursiva hay una nueva llamada a
sí misma. La función de Ackermann se define por recursividad como sigue:

Recursividad cruzada o indirecta


Son algoritmos donde una función provoca una llamada a sí misma de forma
indirecta, a través de otras funciones.

También podría gustarte