You are on page 1of 22

RECURSIN

Definicin
Un procedimiento o funcin se dice recursivo
si durante su ejecucin se invoca directa o
indirectamente a s mismo. Esta invocacin
depende al menos de una condicin que
acta como condicin de corte que provoca
la finalizacin de la autoinvocacin.

Definicin
Repeticin por autoreferencia, cuando una
funcin se invoca a s misma (puede ser en
forma directa o indirecta).
Es la forma en la cual se especifica un proceso
basado en su propia definicin, pero con
menor complejidad. De esta forma, en algn
momento se llega a un proceso muy simple
que puede resolverse facilmente (se llama
solucin trivial).

Parece un concepto nuevo, pero ya lo hemos visto en


varias definiciones matemticas
Definiciones por induccin
El uno pertenece a los Naturales, y si N pertenece a los
Naturales, N+1 tambin.
Factorial(0) = 1 (solucin trivial)
Factorial(N) = N * Factorial(N-1), para todo N > 0.
0!=1
N ! = N * (N - 1) !

Desarrollo de la funcin factorial


int factorial (int x)
{
int rta;
If ( x = = 0)
rta = 1;
else
rta = x * factorial (x-1) ;
return rta;
}

z = factorial(3)
{ int rta;
if (3 = = 0) rta = 1;
else
rta= 3 * factorial(2)
{ int rta;
if (2 = = 0) rta = 1;
else
rta= 2 * factorial(1)
{ int rta;
if (1 = = 0) rta = 1;
else
rta= 1 * factorial(0)
{ int rta;
if (0 = = 0) rta = 1;
return rta;}

return rta;
return rta; }
}
return rta;
}

Cmo funciona esto ??


En el momento de realizar una invocacin recursiva,
se suspende la ejecucin de la funcin invocante
hasta que se termina de resolver la funcin
invocada.
Si bien es la misma funcin la que se invoca, se
genera un nuevo espacio de memoria para la
resolucin de la misma.
Cada espacio tiene sus propias variables locales y
parmetros, con valores propios.

Para poder resolver factorial(3), primero se


debe resolver factorial(2), pero
Para poder resolver factorial(2), primero se
debe resolver factorial(1), pero
Para poder resolver factorial(1), primero se
debe resolver factorial(0), y
factorial(0) es 1

Reglas de la buena recursin


Toda funcin recursiva debe tener:
1. Al menos una Condicin de Corte con su
respectiva Solucin Trivial.
2. Al menos una Llamada Recursiva (o Entrada en
Recursin).
3. En cada Llamada Recursiva, se vuelve a
invocar el mismo algoritmo, pero con un caso
ms simple de resolver. Se produce un
acercamiento a la Condicin de Corte.
4. Al llegar a la Solucin Trivial, queda expresada
la solucin total (considerando toda la frmula
que qued pendiente de resolver).

int factorial (int x)


{
Condicin de Corte
int rta;
If ( x = = 0)
Solucin Trivial
rta = 1;
else
rta = x * factorial (x-1) ;
return rta;
}
Llamada Recursiva

Acercamiento a la
Condicin de Corte

Usar recursin cuando:


1.

La estructura de la funcin es recurrente y el


algoritmo resulta ms sencillo.

2.

La estructura de datos es recursiva.

Definicin de Lista
estructura de datos recursiva

El NULL es una Lista y adems, un


Nodo seguido de una Lista
tambin es Lista.

Ejemplo: recorrer una lista vinculada


Se trata de una estructura de datos recursiva. Considerar la
estructura que define al nodo.
void recorrer( Nodo * lista)
{
Condicin de Corte
if (lista != NULL)
Corta cuando es falso
{
printf(%d, lista->dato);
recorrer(lista->siguiente);
}
Acercamiento a la
}
Condicin de Corte
Llamada Recursiva
Solucin Trivial: ausencia de ELSE. No hace nada al llegar a NULL

Qu hace el siguiente cdigo?


void recorrer( Nodo * lista)
{
if (lista != NULL)
{
recorrer(lista->siguiente);
printf(%d, lista->dato);
}
}

Tener en cuenta que para recorrer la lista NO hace


falta usar while ni for. Ni ningn otra estructura de
repeticin. En vez de eso, se tiene que:
La recursin se encarga de repetir el algoritmo
(printf en este caso).
2. La Llamada Recursiva con el acercamiento a la
condicin de corte hace que se avance en la lista.
3. La condicin de corte finaliza el recorrido de la
lista, justo cuando la lista se termina.
4. La solucin trivial resuelve el algoritmo para la
lista ms simple, o sea la lista nula. Y la solucin
es no hacer nada, en este caso no imprimir.
1.

Cmo se piensa en forma recursiva ?


1. Encontrar la solucin trivial.
2. Armar la expresin de la solucin total
del problema, contando con la solucin
al problema para una etapa una vez
mas cercana a la solucin trivial.
Las reglas de la buena recursin completan
todo lo que falta para que esta forma
simple de razonamiento d resultado.

Ejemplo: sumar el contenido de una lista de


enteros.
Para solucionar este problema planteo el siguiente algoritmo:
La suma de una lista vaca es 0
La suma de los nmeros de una lista ser igual a la suma
entre el primero y el resultado de la suma de la sublista
siguiente.
En este caso particular del ejemplo de la lista, se separa el
primer elemento y se supone conocida la solucin de los
restantes. Tambin se le llama separarlo en cabeza y
cola.

int suma(Nodo * lista)


{
int rta;
if(lista == NULL)
//La suma de una lista vaca es 0

rta = 0;
cola
cabeza
else
rta = lista->dato + suma(lista->siguiente);
/*La suma de los nmeros de una lista ser igual a la
suma entre el primero y el resultado de la suma de la
sublista siguiente.*/

return rta;
}

Ejemplo: determinar si un arreglo es capica.

int capicua(int a[], int i, int j)


{ int rta;
if(i<j) //condicin de corte
if(a[i] == a[j]) //condicin de corte
rta = capicua(a, i+1, j -1); //recursin
else
rta = 0; //solucin trivial
else
rta = 1; //solucin trivial
return rta;
}

Relacin entre Recursin e Iteracin


Tanto la iteracin como la recursin:

se basan en una estructura de control: la iteracin utiliza una


estructura de repeticin y la recursin una estructura de seleccin.

incluyen repeticion: la iteracin utiliza una estructura de repeticin


de forma explcita; mientras que la recursin consigue la repeticin
mediante llamadas de funcin repetidas.

incluyen una prueba de terminacin: la iteracin termina cuando


falla la condicin de continuacin del ciclo; la recursin termina
cuando se reconoce el caso base.

pueden ocurrir de forma infinita: la iteracin se puede quedar en


ciclo infinito si la condicin del ciclo nunca se hace falsa; la
recursin se har infinita si el paso de recursin no reduce el
problema de tal forma que converja al caso base.
La recursin invoca de manera repetida, y por lo tanto, puede
sobrecargar las llamadas de funcin. Esto puede resultar costoso tanto
en tiempo de procesador como en espacio de memoria.

Recursin e Iteracin
Si un lenguaje de programacin como C provee tanto recursin como
iteracin, cul de los dos mtodos debera ser usado para resolver un
problema dado?
En una solucin recursiva el computador debe controlar y resolver
cada una de las invocaciones manteniendo informacin acerca del
resultado las mismas.
Esto puede ser costoso en tiempo y espacio.
En general, se recomienda el uso de una solucin recursiva slo en
caso que:

la solucin no puede ser fcilmente expresable iterativamente (sucede


frecuentemente).

la eficiencia de la solucin recursiva es satisfactoria.

You might also like