You are on page 1of 11

Unidad 4.- Recursividad.

4.1 Definicin.
4.2 Procedimientos recursivos.
4.3 Mecnica de recursin.
4.4 Transformacin de algoritmos recursivos a
iterativos.
4.5 Recursividad en el diseo.
4.6 Complejidad de los algoritmos recursivos.

Recursin
La recursin es un concepto amplio, difcil de precisar. Aparece en
numerosas actividades de la vida diaria, por ejemplo, en una
fotografa de una fotografa. Otro caso muy ilustrativo de recursin es
el que se presenta en los programas de televisin 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. Aqu nos
limitaremos a estudiar la recursividad desde el punto de vista de
programacin.
La recursin permite definir un objeto (problemas, estructuras de
datos) en trminos de s mismo. Casos tpicos de estructuras de
datos definidas de manera recursiva son los rboles y las listas
ligadas. Algunos ejemplos de problemas que se definen
recursivamente son el factorial de un nmero, la serie de Fibonacci,
etc.

Definicin de recursividad
Un subprograma que se llama a s mismo se dice que es recursivo.
Ejemplo de Recursividad
Un ejemplo clsico donde se presenta la recursividad es en la
definicin de un factorial: El factorial de N es la multiplicacin de N
por el Factorial de N-1. Sea eso:
Factorial(N) = N * Factorial(N-1) Ntese que la definicin de la funcin
se realiza en base a si misma. Para que la ejecucin de este cdigo
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)

Procedimientos recursivos
Un procedimiento recursivo es aqul que se llama a s mismo.
En el siguiente procedimiento se utiliza la recursividad para calcular el
factorial de su argumento original.
Java o C#
Public static int factorial(int n)
{
If (n <= 1)
return 1;
else
return n * factorial(n 1);
}

Consideraciones sobre procedimientos recursivos


Condiciones de limitacin. Debe designar un procedimiento recursivo para
probar al menos una condicin que pueda poner fin a la recursividad; tambin
debe supervisar los casos en los que no se satisface ninguna condicin dentro
de un nmero razonable de llamadas recursivas. Si no existe al menos una
condicin que pueda cumplirse sin errores, el procedimiento corre un riesgo
elevado de ejecutarse en un bucle infinito.
Uso de la memoria. La aplicacin tiene una cantidad de espacio limitada para
las variables locales. Cada vez que un procedimiento se llama a s mismo,
utiliza ms cantidad de ese espacio para las copias adicionales de sus
variables locales. Si este proceso contina indefinidamente, se acaba
produciendo un error Stack Overflow Exception?.

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 diseo presenta los mismos problemas que un
procedimiento recursivo nico, pero puede ser ms difcil de detectar y
depurar.
Llamadas con parntesis. Cuando un procedimiento se llama a s mismo de
manera recursiva, debe agregar parntesis detrs del nombre del
procedimiento, aun cuando no exista una lista de argumentos. De lo
contrario, se considerar que el nombre de la funcin representa al valor
devuelto por sta.
Pruebas Si escribe un procedimiento recursivo, debe probarlo
minuciosamente para asegurarse de que siempre cumple ciertas
condiciones de limitacin. Tambin debera comprobar que la memoria no
resulta insuficiente debido a la gran cantidad de llamadas recursivas.

MECANICA DE RECURSION.
Es mucho mas difcil desarrollar una solucin 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 razn para buscar una
solucin recursiva. La mayora de los problemas pueden resolverse de
una manera directa usando mtodos no recursivos. Sin embargo, otros
pueden resolverse de una manera mas lgica y elegante mediante la
recursin. Volviendo a examinar la funcin factorial. El factor es,
probablemente, un ejemplo fundamental de un problema que no debe
resolverse de manera recursiva, dado que su solucin iterativa es
directa y simple. Sin embargo, examinaremos los elementos que
permiten dar una solucin recursiva.
Antes que nada, puede reconocerse un gran nmero 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 solucin no recursiva pueda obtenerse en forma
directa. Es el caso de 0!, que se define como 1. El siguiente paso es
encontrar un mtodo para resolver un caso complejo en trminos de
uno mas simple, lo cual permite la reduccin de un problema

Examinaremos que significa lo anterior cuando se aplica la funcin


factorial. 4! Es un caso mas complejo que 3!. La transformacin que
se aplica al numero a 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 trminos de 3! y, en general, n!
en trminos de (n 1)!, se podr calcular 4! mediante la definicin
de n! en trminos de (n 1)! al trabajar, primero hasta llegar a 0! y
luego al regresar a 4!. En el caso de la funcin factorial se tiene una
definicin 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] * ] = 24
Estos son los ingredientes esenciales de una rutina recursiva: poder
definir un caso complejo en trminos de uno ms simple y tener
un caso trivial (no recursivo) que pueda resolverse de manera
directa. Al hacerlo, puede desarrollarse una solucin si se supone
que se ha resuelto el caso ms simple. La versin C de la funcin
factorial supone que esta definido (n 1)! y usa esa cantidad al
calcular n!.

Con respecto al ejemplo de la funcin de Fibonacci, se definieron dos casos


triviales: fib(0) = 0 y fib(1) = 1. Un caso complejo fib(n) se reduce entonces a dos
ms simples: fib(n 1) y fib(n 2). Esto se debe a la definicin 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 funcin
de Fibonacci no est definida para nmeros negativos.

Consideraciones de la recursividad
Los parmetros y variables locales toman nuevos valores en cada llamada (no
se trabaja con los anteriores).
Cada vez que se llama un mtodo, el valor de los parmetros y
variables locales se almacenan en la pila de ejecucin. Cuando
termina la ejecucin se recuperan los valores de la activacin anterior.
El espacio necesario para almacenar los valores en memoria (pila) crece en
funcin de las llamadas.
Con cada llamada recursiva se crea una copia de todas las variables y
constantes que estn vigentes, y se guarda esa copia en la pila.
Adems se guarda una referencia a la siguiente instruccin a
ejecutar.
Al regresar se toma la imagen guardada (registro de activacin) en el tope de
la pila y se contina operando. Esta accin se repite hasta que la pila quede
vaca.

You might also like