Vous êtes sur la page 1sur 6

ALGORITMOS Y ESTRUCTURAS DE DATOS

- 123 -



CAPTULO 9
RECURSIVIDAD
INTRODUCCIN
En el captulo anterior se present el concepto de estructuras dinmicas y el de nodo. Como se
observ, en la declaracin del tipo de datos para un nodo se hace referencia al propio tipo. Esto es una
de las formas de la recursividad.
En este captulo se plantear el concepto de recursividad y su uso para formular soluciones a
problemas que por sus caractersticas requieren algoritmos que se llaman a s mismos.
Se reescribirn algoritmos que ya se trataron anteriormente utilizando este concepto, como ser
el caso del factorial de un nmero, el recorrido de listas enlazadas y la insercin ordenada de nodos en
ella.
Estos algoritmos nos irn introduciendo en el prximo captulo, cuando se tratarn rboles co-
mo un Tipo Abstracto.
Finalmente veremos algunos aspectos que se deben tener en cuenta antes de decidir la imple-
mentacin de un algoritmo recursivo, por lo que tambin se har una comparacin entre soluciones
iterativas y recursivas.
ALGORITMOS Y ESTRUCTURAS DE DATOS
- 124 -
9.1 RECURSIVIDAD
Es una herramienta de programacin que permite resolver problemas evolutivos, donde un m-
dulo de programa se invoca a s mismo.
Permite disear la solucin de un problema por resolucin de instancias menores del mismo
problema. Usando la recursividad, el problema se resuelve parcialmente en distintas instancias de eje-
cucin del mismo algoritmo, donde cada una, en cierto sentido, es ms simple.
Decimos entonces que, un mdulo es recursivo si dentro de l hay un llamado a s mismo. Si la
solucin de un problema requiere un mdulo donde se realizan llamados a s mismo, decimos que el
mdulo es recursivo.
Otra forma de recursividad se da cuando un mdulo invoca a un segundo mdulo y ste, a su
vez, vuelve a invocar al primero. Decimos que este es un caso de recursividad indirecta.
La recursividad tambin se puede dar en las declaraciones de tipos de datos. Como vimos ante-
riormente, la declaracin de los tipos de datos para un nodo requiere un puntero del mismo tipo que se
est declarando, es decir, hacemos referencia al tipo durante la propia declaracin del tipo.
De acuerdo a lo sealado, en nuestro pseudocdigo no habr algoritmos completamente recur-
sivos, solo habr procedimientos o funciones recursivas.
9.1.1 ASPECTOS A TENER EN CUENTA PARA EL USO DE LA RECURSIVIDAD
En primer trmino, se debe tener en cuenta que el llamado al mdulo dentro del mdulo debe
estar condicionado, caso contrario se estarn haciendo infinitos llamados al mismo mdulo. Un mdulo
tpico que utiliza la recursividad puede verse de la siguiente forma:
procedimiento modulo(tipoDato dato1, tipoDato dato2,)
tipoDato var1, var2, // declaracin de variables auxiliares
inicio
// acciones previas al llamado recursivo
si (condicin) entonces // condicin que debe cumplirse para el llamado
modulo(dato1, dato2, ) // llamado al mismo mdulo (recursividad)
finsi
// acciones posteriores al llamado recursivo
finprocedimiento
Obsrvese que en el llamado se debe respetar el pasaje de parmetros, donde el valor contenido
en dato deber ser distinto en cada llamado.
La solucin a un problema solo se podr obtener a travs de un algoritmo recursivo si el pro-
blema tiene un caso especial cuya solucin es inmediata, es decir, no requiere la solucin de una instan-
cia menor del mismo problema.
Veamos un ejemplo. El factorial de un nmero se define como: n! = n * (n-1)!. Como se puede
observar, la solucin del factorial de n necesita que se calcule previamente el factorial de n-1, luego ste
necesitar el resultado del factorial de n-2 y as sucesivamente. Finalmente se define que factorial de 0
es 1 (0! = 1), este constituye el caso especial que no requiere de ninguna solucin parcial. Entonces,
podramos definir a la funcin factorial como:
Si n = 0 entonces 0! = 1, sino n! = n * (n-1)!
Reemplazando los smbolos de factorial por variables podemos resolver este problema utilizan-
do un algoritmo recursivo. Ms adelante en este captulo se presenta la funcin factorial recursiva.
ALGORITMOS Y ESTRUCTURAS DE DATOS
- 125 -
Tambin deber tenerse en cuenta que el llamado que define a la recursividad (llamado al m-
dulo dentro del mismo mdulo) no puede estar en un bucle, debe estar en una estructura condicional.
Otro aspecto es que toda solucin recursiva tambin tiene una solucin iterativa (con estructu-
ras repetitivas). Entonces, cundo se debe utilizar la solucin recursiva y cundo la iterativa? Cules
son las ventajas y desventajas del uso de la recursividad?
Cuando la solucin del problema requiere un algoritmo con estructuras repetitivas poco claro o
muy complejo y la solucin recursiva es simple de entender y programar utilizaremos la recursividad,
caso contrario se recomienda utilizar estructuras repetitivas.
Una desventaja de la recursividad es el excesivo uso de los recursos del sistema de computa-
cin. Observemos nuevamente el ejemplo de cdigo presentado ms arriba: ste posee parmetros de
entrada y variables locales. Como ya sabemos, cada llamado a un mdulo crea e inicializa variables
locales y parmetros. Adems, como se mencion antes, es necesario almacenar en una pila el estado
del algoritmo que invoca al mdulo y la direccin de retorno para restaurar la ejecucin de ste cuando
finaliza la ejecucin del mdulo. Esto hace que las soluciones recursivas requieran muchos recursos del
sistema. Para disminuir este problema, se recomienda que los mdulos recursivos utilicen pocas varia-
bles locales.
9.2 CONCLUSIONES
Como regla general tenemos:
USAR RECURSIVIDAD SI:
- Los algoritmos que resuelven el problema con recursividad son simples y claros.
- Los algoritmos iterativos que resuelven el problema son complicados de entender.
- Soluciones a problemas complejos.
- Cuando el problema a resolver es de carcter recursivo (son ejemplos el factorial de un n-
mero y la serie de Fibonacci).
- Cuando los datos involucrados en el problema estn organizados en estructuras que se defi-
nen recursivamente, como listas, rboles y grafos.
DESVENTAJAS DE LA RECURSIVIDAD
- Sobrecarga asociada con las llamadas a mdulos.
- Una llamada puede generar un gran nmero de llamadas vinculadas recursivas.
- La claridad compensa la sobrecarga?
- El valor de la recursividad reside en el hecho de que se puede usar para resolver problemas
sin fcil solucin iterativa.
- La ineficiencia inherente de algunos algoritmos recursivos.
- Excesivo uso de recursos de memoria y procesamiento.
- El lenguaje de programacin a utilizar requieren tener manejo dinmico de memoria.
9.3 EJEMPLOS
A continuacin se presentan algunos ejemplos de uso de la recursividad a problemas que ante-
riormente se solucionaron con algoritmos iterativos.
EJEMPLO 9.3.1: Factorial de un nmero natural.
Como se mencion antes, el factorial de un nmero n se resuelve con un algoritmo recursivo
que se invoca sucesivamente con valores menores a n hasta 0 (cero), donde se define que factorial de 0
(cero) es 1 (uno).
ALGORITMOS Y ESTRUCTURAS DE DATOS
- 126 -
variables
entero n
real fact
inicio
// acciones previas al clculo del factorial
leer (n) // se lee el nmero para el cual se calcular el factorial
si (n > 0) entonces // si el nmero ledo es natural, se calcula el factorial
fact factorial(n) // llamado a la funcin para calcular el factorial del nmero
finsi
// contina el cdigo
fin // fin del algoritmo principal
real funcion factorial (entero n)
real fact // variable local en la que se almacena el resultado
inicio
si (n <> 0)entonces
fact n * factorial(n-1) // primero se debe calcular (n-1)!
sino
fact 1 // Se define: 0! = 1
finsi
retornar(fact) // Se devuelve el valor obtenido
finfuncion
EJEMPLO 9.3.2: Recorrido de una Lista Enlazada Simple.
La solucin iterativa de este problema tambin se present con anterioridad. Aqu se asume que
se tiene una lista enlazada cuyos nodos solo contienen nmeros. Se recorre la lista para mostrar (escri-
bir) su contenido.
tipo numeros
entero num
numeros sgte
fintipo
variables
numeros L, p
inicio
// acciones previas , se crea la lista
recorrer (L) // llamado al procedimiento recorrer (recursivo)
// contina el cdigo
fin // fin del algoritmo principal
procedimiento recorrer(numeros p)
inicio
si (p <> Null)entonces // Se verifica si se lleg al final de la lista
escribir(pnum) // no es el final: se escribe el dato contenido en el nodo
recorrer(psgte) // y se llama a recorrer (siguiente nodo)
finsi
finprocedimiento
EJEMPLO 9.3.3: Insercin de un nodo al final de una Lista Enlazada Simple.
La solucin consiste en hallar el ltimo nodo y hacer que su siguiente sea el nuevo nodo. Utili-
zamos la lista enlazada del ejemplo anterior.
ALGORITMOS Y ESTRUCTURAS DE DATOS
- 127 -
tipo numeros
entero num
numeros sgte
fintipo
variables
numeros L, p
Inicio
// acciones previas , se crea la lista
p nuevo(numeros) // se solicita espacio de memoria para el nuevo nodo
si (p <> Null) entonces // se cre el nodo
leer (pnum) // leemos del nmero que se almacenar en el nodo
psgte Null // el nodo ser el ltimo, no tiene siguiente
L insertar (p, L) // insertar el nodo apuntado por p en la lista L
finsi
// contina el cdigo
Fin // fin del algoritmo principal
numeros funcion insertar(numeros p, numeros r)
inicio
si (r <> Null)entonces
rsgte insertar(p, rsgte)
sino
r p
finsi
retornar(r)
finprocedimiento
Comentarios sobre la funcin: se debe hallar el final de la lista (r = Null). Como el algoritmo es
recursivo, si no se lleg a esta situacin lo volvemos a llamar pasando la direccin del nodo siguiente.
Si estamos con el puntero de recorrido r en Null (final de la lista), hacemos que ste seale al nuevo
nodo (r p) y retornamos su direccin. Al retornar, estamos saliendo del llamado (volvemos al nodo
anterior) con lo cual la direccin devuelta (la del nuevo nodo) se asigna como siguiente del nodo actual
(ltimo nodo) y el nuevo nodo queda al final de la lista.
EJEMPLO 9.3.4: Insercin de un nodo en una Lista Enlazada Simple Ordenada.
La solucin consiste en hallar la ubicacin del nodo en la lista y hacer que su siguiente sea el
primer nodo que contenga un nmero mayor. Utilizamos la lista enlazada del ejemplo anterior (pero
ahora ordenada). Como solo vara la funcin insertar respecto de lo ya presentado, solo se mostrar el
cdigo de sta.
numeros funcion insertar(numeros p, numeros r)
inicio
si (r <> Null)entonces
si (pnum < rnum) entonces
psgte r
r p
sino
rsgte insertar(p, rsgte)
finsi
sino
r p
finsi
retornar(r)
finprocedimiento
ALGORITMOS Y ESTRUCTURAS DE DATOS
- 128 -
Comentarios sobre la funcin: como puede observarse, es bastante similar a la anterior. La dife-
rencia se encuentra en la comparacin del valor almacenado en el nuevo nodo con los valores almace-
nados en los nodos de la lista para hallar su ubicacin: si el ordenamiento de los datos en la lista es de
menor a mayor, se debe hallar un nodo que posea un valor mayor al que se est por insertar, hacer que
ste sea el siguiente del nuevo nodo (psgte r) y retornar la direccin del nuevo nodo (r p).
Por otra parte, si en la bsqueda llegamos a r = Null, significa que el nuevo nodo posee el mayor valor
y debe insertarse al final.
Los algoritmos recursivos para listas enlazadas simples no utilizan punteros auxiliares al nodo
anterior; sin embargo, cada llamado crea nuevos punteros auxiliares, por lo que en cada nodo visitado
se deja un puntero sealndolo. Como los dos ltimos algoritmos poseen dos parmetros (los punteros
p y r), cada llamado crea un espacio de memoria para cada uno de ellos: El espacio total de memoria
ocupado por la recursividad depende directamente de la cantidad de nodos que posee la lista.
Estos ltimos algoritmos son importantes para comprender el ltimo tema de esta ctedra: Es-
tructuras Dinmicas no Lineales, en especial los rboles.
Los algoritmos no recursivos para construir y mantener rboles son sumamente difciles de in-
terpretar, por lo que se utiliza la recursividad.

Vous aimerez peut-être aussi