Está en la página 1de 15

Recursividad.

Unidad II.- Recursividad.

2.1 Concepto de recursividad.

La recursividad es una tcnica de programacin importante. Se utiliza para


realizar una llamada a una funcion desde la misma funcion. Como ejemplo til se
puede presentar el clculo de nmeros factoriales. l factorial de 0 es, por
definicin, 1. Los factoriales de nmeros mayores se calculan mediante la
multiplicacin de 1 * 2 *, incrementando el nmero de 1 en 1 hasta llegar al
nmero para el que se est calculando el factorial.

El siguiente parrafo muestra una funcin, expresada con palabras, que


calcula 8-un factorial.

Si el nmero es menor que cero, se rechaza. Si no es un entero, se


redondea al siguiente entero. Si el nmero es cero, su factorial es uno. Si el
nmero es mayor que cero, se multiplica por l factorial del nmero menor
inmediato.

Para calcular el factorial de cualquier nmero mayor que cero hay que
calcular como mnimo el factorial de otro nmero. La funcin que se utiliza es la
funcin en la que se encuentra en estos momentos, esta funcin debe llamarse a
s misma para el nmero menor inmediato, para poder ejecutarse en el nmero
actual. Esto es un ejemplo de recursividad.

La recursividad es un concepto importante en informatica. Muchos algoritmos


se pueden describir mejor en terminos de recursividad.

Supongamos que P es un procedimiento que contiene una sentencia de


Llamada a si mismo o una sentencia de Llamada a un segundo procedimiento que
puede eventualmente llamar de vuelta al procedimiento original P. Entonces P se
dice que es u procedimiento recursivo. Como el progrma no ha de continuar
ejecutandose indefinidamente, un procedimiento recursivo ha de tener las dos
siguientes propiedades:
(1) Debe existir un cierto criterio, llamado criterio base, por el que el
procedimiento no se llama asi mismo.
(2) Cada vez que el procedimiento se llame a si mismo (directa o
inderectamente), debe estar mas cerca del criterio base.

Un procedimiento recursivo con estas dos propiedades se dice que esta bien
definido.
Similarmente, una funcion se dice que esta definida recursivamente si la
definicion de la funcion se refiere a si misma. De nuevo, para que la definicion no
sea circular, debe tener las dos siguientes propiedades:

(1) Debe haber ciertos argumentos, llamados valores base, para los que la
funcion no se refiera a si misma.
(2) Cada vez que la funcion se refiera a si misma, el argumento de la funcion
debe acercarse mas al valor base.

Una funcion recursiva con estas dos propiedades se dice tambien que esta
bien definida.

Tipos.

Podemos distinguir dos tipos de recursividad:

Directa: Cuando un subprograma se llama a si mismo una o mas veces


directamente.
Indirecta: Cuando se definen una serie de subprogramas usndose unos a
otros.

Caractersticas.

Un algoritmo recursivo consta de una parte recursiva, otra iterativa o no


recursiva y un acondicin de terminacin. La parte recursiva y la condicin de
terminacin siempre existen. En cambio la parte no recursiva puede coincidir con
la condicin de terminacin. Algo muy importante a tener en cuenta cuando
usemos la recursividad es que es necesario asegurarnos que llega un momento
en que no hacemos ms llamadas recursivas. Si no se cumple esta condicin el
programa no parar nunca.

Ventajas e inconvenientes.
La principal ventaja es la simplicidad de comprensin y su gran potencia,
favoreciendo la resolucin de problemas de manera natural, sencilla y elegante; y
facilidad para comprobar y convencerse de que la solucin del problema es
correcta. El principal inconveniente es la ineficiencia tanto en tiempo como en
memoria, dado que para permitir su uso es necesario transformar el programa
recursivo en otro iterativo, que utiliza bucles y pilas para almacenar las variables.

2.2 Procedimientos recursivos.

Un procedimiento o funcin recursiva es aquella que se llama as misma.


Esta caracterstica permite a un procedimiento recursivo repetirse valores
diferentes de parmetros. La recursion es una alternativa a la iteracin muy
elegante en la solucin de problemas, especialmente si estos tienen naturaleza
recursiva.
Normalmente, una solucin recursiva es menos eficiente en trminos de
tiempo de computadora que una solucin iterativa debido al tiempo adicional de
llamada a procedimientos.
En muchos casos, la recursion permite especificar una solucin mas simple y
natural para resolver un problema que en otro caso seria difcil. Por esta razn la
recursion (recursividad) es una herramienta muy potente para la resolucin de
problemas de programacin.

En el siguiente ejemplo se muetra un procedimiento recursivo.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
public partial class Recursividad : Form
{
public Recursividad()
{
InitializeComponent();
}
double r;
int fin = 0;
private void button1_Click(object sender, EventArgs e)
{
fin = int.Parse(textBox4.Text.ToString());
listBox1.Items.Clear();
listBox1.Items.Add("x\ty");
evaluar();
}
//Procedimiento recusivo
public void evaluar()
{
while (fin <= int.Parse(textBox5.Text.ToString()))
{
r = int.Parse(textBox1.Text.ToString()) * (fin * fin) +
int.Parse(textBox2.Text.ToString()) * fin +
int.Parse(textBox3.Text.ToString());
listBox1.Items.Add(fin.ToString() + "\t" + r.ToString());
fin++;
evaluar();
}
}
}
}

Mecnica de recursin.

Un objeto recursivo es aquel que forma parte de si mismo. Esta idea puede
servir de ayuda para la definicin de conceptos matematicos. Asi, la definicin del
conjunto de los numeros naturles es aque conjunto en el que se cumplen las
siguientes caracteristicas:

0 es un nmero natural.
El siguiente nmero de un nmero natural es otro numero natural.

Mediante una definicin finita hemos representado un conjunto infinito.

El concepto de la recursividad es muy importante en programacin. La


recursividad es una herramienta muy eficaz para resolver diversos tipos de
problemas existen muchos algoritmos que se describiran mejor en terminos
recursivos.

Dentro de la teora de la recursin, se tiene que existen diferentes tipos de


recursin:

Recursin directa.

Cuando el cdigo F tiene una sentencia que involucra a F.


Recursin indirecta o cruzada

Cuando la funcin F involucra una funcin G que invoca a la ves una funcin
H, y as sucesivamente, hasta que se involucra la funcin F. Por ejemplo el
algoritmo de Par o impar.

int par (int n)

{ if (n==0) return n+1;

return impar(n-1);

int impar(int n)

if (n==0) return 0;

return par(n-1);
}
A continuacin se expone otro ejemplo de programa que utiliza recursin
indirecta, y nos dice si un nmero es par o impar. Cabe mencionar que existen
otros mtodos mucho ms sencillos para determinar la solucin a este problema,
basta con determinar el resto de la divisin entre dos. Por ejemplo: si hacemos
par(2) devuelve 1 (cierto). Si hacemos impar (4) devuelve 0 (falso).

int par(int n);


int impar(int n);

int par(int n)
{ if (n == 0) return 1;

return impar(n-1);
}
int impar(int n)
{ if (n == 0) return 0;

return par(n-1);
}

Recursin simple.- Aquella en cuya funcin solo aparece una llamada


recursiva. Se puede transformar con facilidad en algoritmos iteractivos.

Recursin mltiple.- Se da cuando hay ms de una llamada a s misma


dentro del cuerpo de la funcin, resultando ms difcil de transformar a iteractiva.
Poe ejemplo el algoritmo de Fibonacci.

int fibo(int n)
{ if (n<=1) return 1

return fibo(n-1) + fibo(n-2)


}
4.3.1.5.- Recursin anidada.- En algunos de los argumentos de la llamada
hay una nueva llamada a s misma. Por ejemplo la funcin de Ackerman:

int Ack(int m, int n)


{ if (m==0) return n+1

if (n=00) return Ack(n-1, 1)

return Ack(m-1, Ack(m, n-1));


}

Un requisito para que un algoritmo recursivo sea correcto es que no genere


una secuencia infinita de llamadas sobre s mismo. Cualquier algoritmo que
genere una secuencia de este tipo no terminar nunca. En consecuencia, la
definicin recursiva debe incluir un componente base (condicin de salida ) en el
que f(n) se define directamente (es decir, no recursivamente) para uno o ms
valores de n. Debe existir una <> de la secuencia de llamadas recursivas.

Al estar trabajando con recursividad, la memoria de la computadora hace uso


de una pila de recursin, la cual se divide de manera lgica en 4 segmentos:
1. Segmento de cdigo.- Parte de la memoria donde se guardan las
instrucciones del programa en cdigo mquina.
2. Segmento de datos.- Parte de la memoria destinada a almacenar las
variables estticas.
3. Montculo.- Parte de la memoria destinada a las variables dinmicas.
4. Pila de programa.- parte destinada a las variables locales y parmetros de
la funcin que est siendo ejecutada.

Funciones mutuamente recursivas.

Cuando se trabaja llamados a la ejecucin de las funciones, se provocan las


siguientes operaciones:

1. Reservar espacio en la pila para los parmetros de la funcin y sus


variables locales.
2. Guardar en la pila la direccin de la lnea de cdigo desde donde se ha
llamado a la funcin.
3. Almacenar los parmetros de la funcin y sus valores de pila.
4. Al terminar la funcin, se libera la memoria asignada en la pila y se vuelve a
la instruccin actual.
Pero cuando se trabaja con funciones recursivas, se provoca adems lo
siguiente:

1. La funcin se ejecutar normalmente hasta la llamada a s misma. En ese


momento se crean en la pila nuevos parmetros y variables locales.
2. El nuevo ejemplar de funcin comienza a ejecutarse.
3. Se crean ms copias hasta llegar a la primera llamada (ultima en cerrarse).

La ciencia de la computacin hace tiempo que descubri que se puede


reemplazar a un mtodo que utiliza un bucle para realizar un clculo con un
mtodo que se llame repetidamente a s mismo para realizar el mismo clculo. El
hecho de que un mtodo se llame repetidamente a s mismo se conoce como
recursion.

La recursin trabaja dividiendo un problema en subproblemas. Un programa


llama a un mtodo con uno o ms parmetros que describen un problema. Si el
mtodo detecta que los valores no representan la forma ms simple del problema,
se llama a s mismo con valores de parmetros modificados que describen un
subproblema cercano a esa forma.

Esta actividad contina hasta que el mtodo detecta la forma ms simple del
problema, en cuyo caso el mtodo simplemente retorna, posiblemente con un
valor, si el tipo de retorno del mtodo no es void. La pila de llamadas a mtodo
empieza a desbobinarse como una llamada a mtodo anidada para ayudar a
completar una evaluacin de expresin. En algn punto, la llamada el mtodo
original se completa, y posiblemente se devuelve un valor.

Recursin infinita

La iteracin y la recursin pueden producirse infinitamente. Un bucle infinito


ocurre si la prueba o test de continuacin del bucle nunca se vuelve falsa. Una
recursin infinita ocurre si la etapa de recursin no reduce el problema en cada
ocasin de modo que converja sobre el caso base o condicin de la salida.

En realidad, larecursin infinita significa que cada llamada recursiva produce


otra llamada recursiva y esta a su vez otra llamada recursiva, y as para siempre.
En la prctica, dicha funcin se ejecutar hasta que la computadora agote la
memoria disponible y se produzca una terminacin anormal del programa. El flujo
de control de una funcin recursiva requiere de tres condiciones para una
terminacin normal.
Cuando no utilizar recursividad.

La solucion recursiva de ciertos problemas simplifica mucho la estructura de


los programas. Como contrapartida, en la mayoria de los lenguajes de
programacin las llamadas recursivas a procedimientos o funciones tienen un
coste de tiempo mucho mayor que sus homologos iterativos. Se puede, por lo
tanto, afrimar que la ejecucin de un programa recursivo va a ser mas lenta y
menos eficiente que el programa iterativo que soluciona el mismo problema,
aunque, a veces, la sencilles de la estructura recursiva justifica el mayor tiempo de
ejecucion.

Los procedimientos recursivos se pueden convertir en no recursivos


mediante la introduccin de una pila y asi emular las llamadas recursivas. De esta
manera se puede eliminar la recursion de aquellas partes de los programas que se
ejecutan ms frecuentemente.

Ejemplo de mecnica de la recursividad

Las torres de Hanoi

Algoritmo para trasladar la torre 1n del poste X al poste Z, usando como


auxiliar el poste Y.

Si n = 1, lleva el disco 1 de X a Z y termina.


Traslada la torre 1n1 usando este mismo algoritmo, de X a Y, usando
como auxiliar Z.
Lleva el disco n de X a Z.
Traslada la torre 1n1 usando este mismo algoritmo, de Y a Z, usando
como auxiliar X. Este algoritmo siempre me ha parecido sorprendente, parece ms
la definicin de un problema que su resolucin. Si eres como yo tendrs que
implementarlo en un lenguaje de programacin concreto para convencerte de que
funciona. En realidad, lo nico que hace es especificar unos pasos inevitables. Por
ejemplo, como vimos antes, para resolver el puzzle es obligatorio llevar el disco n
de A a C, y para ello es obligatorio llevar antes la torre 1n a B, etc. La secuencia
de movimientos que produce este algoritmo es la nica solucin ptima (o sea, de
longitud mnima) posible. El nmero de movimientos es M3(n) = 2n1, como se
puede demostrar fcilmente por induccin sobre el nmero de discos.

Se cumple para n = 1
M3(1) = 1 = 211.
Si se cumple para n, se cumple para d+1
Al ejecutarse el algoritmo para n+1 se llama a s mismo dos veces para n,
ms un movimiento del disco n+1. As que M3(n+1) = 2 M3(n) + 1 = 2 (2n1) +
1 = 2n+12+1 = 2n+11.

Para n = 8 el nmero de movimientos es de 281 = 255. Para n = 64, de


2641 = 18.446.744.073.709.551.615. Si los bramanes de Benars cambiaran un
disco de sitio cada segundo necesitaran ms de quinientos ochenta mil millones
de aos para terminar su tarea, unas cuarenta veces la edad del Universo.

Los algoritmos recursivos funcionan bien con ordenadores, pero son difciles
de aplicar para un ser humano. Si intentas resolver la torre de ocho discos
aplicando el mtodo descrito es fcil que te pierdas a no ser que vayas tomando
notas de por dnde vas. Incluso para los ordenadores los algoritmos recursivos
suelen ser poco econmicos, en el sentido de que consumen bastante memoria
(y es que ellos tambin necesitan tomar notas). La alternativa a los algoritmos
recursivos son los iterativos, en los que no hay llamadas a s mismo, sino uno o
varios bucles. Muy a menudo no existe o no se conoce una alternativa iterativa
para un algoritmo recursivo, y cuando s se conoce, suele ser mucho ms
complicada que la versin recursiva. Sin embargo, en el caso de la Torre de
Hanoi, existen varios algoritmos iterativos muy simples.

Transformacin de algoritmos recursivos a iterativos.

El concepto de recursividad va ligado al de repeticin. Son recursivos


aquellos algoritmos que, estando encapsulados dentro de una funcin, son
llamados desde ella misma una y otra vez, en contraposicin a los algoritmos
iterativos, que hacen uso de ciclos while, do-while, for, etc.
Algo es recursivo si se define en trminos de s mismo (cuando para definirse
hace mencin a s mismo). Para que una definicin recursiva sea vlida, la
referencia a s misma debe ser relativamente ms sencilla que el caso
considerado.

Ejemplo: definicin de n natural:

El N 0 es natural
El N n es natural si n-1 lo es

En un algoritmo recursivo distinguimos como mnimo 2 partes:


a). Caso trivial, base o de fin de recursin:

Es un caso donde el problema puede resolverse sin tener que hacer uso de
una nueva llamada a s mismo. Evita la continuacin indefinida de las partes
recursivas.

b). Parte puramente recursiva:

Relaciona el resultado del algoritmo con resultados de casos ms simples.


Se hacen nuevas llamadas a la funcin, pero estn ms prximas al caso base.

Codigo Recursivo

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication1
{
public partial class Form1 : Form
{
class cap_recursivo
{

public float capital(float m, int n, float x)


{
if (n == 0)
{ return m; }
else
{ return capital(m, n - 1, x) * (1 + (x/100)); }

public Form1()
{
InitializeComponent();

private void Form1_Load(object sender, EventArgs e)


{

private void button1_Click(object sender, EventArgs e)

{
cap sayo = new cap();

label4.Text = int.Parse(sayo.capital());

private void label4_Click(object sender, EventArgs e)


{

}
}
}

Diseo

Codigo Iterativo

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication7
{
public partial class Form1 : Form
{
class cap
{
public float capital(float m, int n, float x)
{
if (n == 0)
{ return m; }
else
{
//x = x / 100;float inn;
//x = x * m;
x = x / 100;

for (int b = n; b > 0; b--)


{
m = m + (x * m);
//m = x + m;
//n = n - 1;(m ) +
}
} return m;

//return capital(m, n - 1, x) * (1 + (x / 100)); }

}
}
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)


{

private void button1_Click(object sender, EventArgs e)


{
cap sayo = new cap();

label4.Text = int.Parse(sayo.capital());

private void label4_Click(object sender, EventArgs e)


{

}
}
}
Diseo Explicacion

Este programa lo que hace es calcular el interes de un monto inicial de


acuerdo a cuanto se pidio prestado, a cuanto porcentaje de interes y el tiempo por
el que fue prestado. Al pasar el primer ao, se calcula el monto inicial + interes =
monto total, y al segundo ao o mas se calcula el monto total + interes y asi
sucesivamente hasta terminar el periodo del prestamo. La forma recursiva se
vuelve a llamar, osea que vuelve a hacer el procedimiento dentro de si misma, y la
iteraria es de forma seguida y larga. No importa si va primero o despues, los dos
tipos llegan al mismo objetivo, son dos diferentes metodos de hacer la misma
accion. El recursivo manda a llamar la misma funcion dentro de si misma y
iterativo hace todo el trabajo seguido.

Recursividad en diseo.

Un procedimiento recursivo es aquel que se llama a s mismo, para poder


funcionar tiene que tener una condicin de salida que del nmero de veces que se
va a llamar a s mismo el procedimiento.
La recursividad en diseo se refiere a la manera de cmo representar los
procedimientos recursivos al momento de disear los programas.
Dependiendo del mtodo que utilicemos para disear la representacin
grfica de la recursividad va a ser diferente sin embargo el procedimiento va a ser
similar ya que el fin es el mismo poner una condicin que nos diga si llamamos al
mtodo o que nos mande terminarlo. Un ejemplo en una funcin genrica seria
este:
METODO1
{
Procedimiento x;
Condicin ( )
{
Llamada al metodo1;
}
Fin;
}

En un diagrama seria algo as:

NOTA: Estos son dos ejemplos en ambos utilizamos una condicin, pero se
pueden utilizar ciclos siempre asegurndonos de que nos den salida en algn
momento.
Lo importante y que tenemos que tomar en cuenta es que la si se cumple el
criterio para llamar el procedimiento hay que apuntar a el inicio del mtodo, y al no
cumplirse debe apuntar al siguiente paso en el procedimiento o al final o
viceversa.

Ejemplo:

Disear un programa que despliegue el contenido de un arreglo el siguiente


arreglo: {a, e, i, o, u}

Seudocdigo:
1. Creamos la forma que contendr una listbox para despliegue.
2. Creamos el arreglo que contendr los elementos (vocales)
3. Despus creamos el mtodo despliegue. El cual contendr:

a. Un ciclo for (int i=0;i 4;i++) dentro del cual se har el despliegue en el
ndice i del arreglo vocales
b. llamar al mtodo despliegue.
4. En el constructor mandamos llamar al mtodo despliegue.

Y listo al abrir nuestro programa vamos a desplegar dentro del listbox el


arreglo mediante la recursividad. Para ver un programa visual de recursividad ver
el tema recursividad.

Complejidad en los algoritmos recursivos.

Un algoritmo recursivo es un algoritmo que se define en trminos de s


mismo. Son implementados en forma de subprogramas (funciones, subrutinas,
procedimientos, etc) de tal forma que dentro de un subprograma recursivo hay una
o ms llamadas a l mismo.

FUNCIN Factorial(n)
INICIO
SI (n<2) ENTONCES
Factorial = 1;
SINO
Factorial = n * Factorial(n-1);
FIN-SI
FIN

Generalmente, si la primera llamada al subprograma se plantea sobre un


problema de tamao u orden N, cada nueva ejecucin recurrente del mismo se
plantear sobre problemas, de igual naturaleza que el original, pero de un tamao
menor que N. De esta forma, al ir reduciendo progresivamente la complejidad del
problema a resolver, llegar un momento en que su resolucin sea ms o menos
trivial (o, al menos, suficientemente manejable como para resolverlo de forma no
recursiva). En esa situacin diremos que estamos ante un caso base de la
recursividad.

También podría gustarte