Você está na página 1de 11

c  c


 

      


c   
   
 
  

c   
  !


 " 
  

Se dice que una función es recursiva cuando se define en función de si misma.


ïo todas la funciones pueden llamarse a si mismas, sino que deben estar
diseñadas especialmente para que sean recursivas, de otro modo podrían
conducir a bucles infinitos, o a que el programa termine inadecuadamente.

Tampoco todos los lenguajes de programación permiten usar recursividad.

C++ permite la recursividad. Cada vez que se llama a una función, se crea un
juego de variables locales, de este modo, si la función hace una llamada a si
misma, se guardan sus variables y parámetros, usando la pila, y la nueva instancia
de la función trabajará con su propia copia de las variables locales. Cuando esta
segunda instancia de la función retorna, recupera las variables y los parámetros
de la pila y continua la ejecución en el punto en que había sido llamada.

Por ejemplo:

Prodríamos crear una función recursiva para calcular el factorial de un número


entero.

El factorial se simboliza como n!, se lee como "n factorial", y la definición es:

n! = n * (n-1) * (n-2) * ... * 1

Hay algunas limitaciones:

v ïo es posible calcular el factorial de números negativos, no está definido.


v El factorial de cero es 1.

De modo que una función bien hecha para cálculo de factoriales debería incluir un
control para esos casos:

/* Función recursiva para cálculo de factoriales */


int factorial(int n) {
if(n < 0) return 0;
else if(n > 1) return n*factorial(n-1); /* Recursividad */
return 1; /* Condición de terminación, n == 1 */
}

Veamos paso a paso, lo que pasa cuando se ejecuta esta función, por ejemplo:
factorial(4):

1a Instancia
n=4
n>1
salida ĸ 4 * factorial(3) (Guarda el valor de n = 4)
2a Instancia
n>1
salida ĸ 3*factorial(2) (Guarda el valor de n = 3)

3a Instancia
n>1
salida ĸ 2*factorial(1) (Guarda el valor de n = 2)

4a Instancia
n == 1 ĺ retorna 1

3a Instancia
(recupera n=2 de la pila) retorna 1*2=2

2a instancia
(recupera n=3 de la pila) retorna 2*3=6

1a instancia
(recupera n=4 de la pila) retorna 6*4=24
Valor de retorno ĺ 24

Aunque la función i   es un buen ejemplo para demostrar cómo funciona una
función recursiva, la recursividad no es un buen modo de resolver esta función,
que sería más sencilla y rápida con un simple bucle .

La recursividad consume muchos recursos de memoria y tiempo de ejecución, y


se debe aplicar a funciones que realmente le saquen partido.

Veamos otro ejemplo: visualizar las permutaciones de n elementos.

Las permutaciones de un conjunto son las diferentes maneras de colocar sus


elementos, usando todos ellos y sin repetir ninguno. Por ejemplo para A, B, C,
tenemos: ABC, ACB, BAC, BCA, CAB, CBA.

#include <iostream>
using namespace ÷;

/* Prototipo de función */
void Permutaciones(char *, int l=0);

int   (int argc, char *argv[]) {


char palabra[] = "ABCDE";

Permutaciones(palabra);


();
return 0;
}

void Permutaciones(char * cad, int l) {


char c; /* variable auxiliar para intercambio */
int i, j; /* variables para bucles */
int n = strlen(cad);

for(i = 0; i < n-l; i++) {


if(n-l > 2) Permutaciones(cad, l+1);
else   << cad << ", ";
/* Intercambio de posiciones */
c = cad[l];
cad[l] = cad[l+i+1];
cad[l+i+1] = c;
if(l+i == n-1) {
for(j = l; j < n; j++) cad[j] = cad[j+1];
cad[n] = 0;
}
}
}

El algoritmo funciona del siguiente modo:

Al principio todos los elementos de la lista pueden cambiar de posición, es decir,


pueden permutar su posición con otro. ïo se fija ningún elemento de la lista, l = 0:
Permutaciones(cad, 0)

0 1 2 3 4
A B C D /0

Se llama recursivamente a la función, pero dejando fijo el primer elemento, el 0:


Permutacion(cad,1)

 1 2 3 4
# B C D /0

Se llama recursivamente a la función, pero fijando el segundo elemento, el 1:


Permutacion(cad,2)

 $ 2 3 4
# % C D /0

Ahora sólo quedan dos elementos permutables, así que imprimimos ésta
permutación, e intercambiamos los elementos: l y l+i+1, es decir el 2 y el 3.
 $ 2 3 4
# % D C /0

Imprimimos ésta permutación, e intercambiamos los elementos l y l+i+1, es decir


el 2 y el 4.

 $ 2 3 4
# % /0 C D

En el caso particular de que l+i+1 sea justo el número de elementos hay que
mover hacia la izquierda los elementos desde la posición l+1 a la posición l:

 $ 2 3 4
# % C D /0

En este punto abandonamos el último nivel de recursión, y retomamos en el valor


de l=1 e i = 0.

 1 2 3 4
# B C D /0

Permutamos los elementos: l y l+i+1, es decir el 1 y el 2.

 1 2 3 4
# C B D /0

En la siguiente iteración del bucle i = 1, llamamos recursivamente con l = 2:


Permutaciones(cad,2)

 $ 2 3 4
# & B D /0

Imprimimos la permutación e intercambiamos los elementos 2 y 3.

 $ 2 3 4
# & D B /0

Y así sucesivamente.

'     
  
^
Existen otras formas de implementar algoritmos recursivos, no es necesario que
una función se invoque a si misma.

Por ejemplo, un par de funciones A y B pueden crear un algoritmo recursivo si la


función A invoca a la función B, y esta a su vez invoca a la función A.

Este mismo mecanismo se puede implementar con tres, cuatro o con cualquier
número de funciones.

Veamos un ejemplo. Partamos de la siguiente serie:

1 - 1/2 + 1/3 - 1/4 + 1/5 - ... - 1/2*n + 1/2*n+1 - ...

Podemos diseñar un procedimiento recursivo para calcular la suma de los


primeros elementos de la serie, de modo que usemos una función diferente para
los elementos pares e impares.

// Suma de la serie 1-1/2+1/3-1/4+1/5...


// (C) 2009 Con Clase
// Salvador Pozo

#include <iostream>

using namespace ÷;

double par(int);
double impar(int);
double suma(int);

int   () {

  << suma(3) << ;


  << suma(13) << ;
  << suma(23) << ;
  << suma(87) << ;
  << suma(250) << ;
  << suma(450) << ;
return 0;
}

double suma(int n) {
if(n % 2) return impar(n);
else return par(n);
}

double par(int n) {
return impar(n-1)-1/double(n);
}

double impar(int n) {
if(n == 1) return 1;
return par(n-1)+1/double(n);
}

Veremos más aplicaciones de recursividad en el tema de estructuras dinámicas de


datos.

((  
^

1. La sucesión de Fibonacci se define como una serie infinita de números


naturales.

El primer término, para n = 0, es 0 y el segundo, para n = 1 es 1. Los


sucesivos se calculan como la suma de los dos términos anteriores. Por
ejemplo, el término 5 es la suma de los términos 3 y 4.

Los primeros términos son: 0, 1, 1, 2, 3, 5, 8...

Hacer un programa que calcule el término n de la sucesión de Fibonacci de


forma recursiva.

2. Volvamos al problema de los palíndromos. Pero ahora usaremos una


función recursiva para determinar si una cadena determinada es o no
palíndroma.
3. Veamos ahora un problema clásico: las torres de Hanói.

Torres de Hanói

El juego consiste en tres varillas verticales. En una de ellas están apiladas


un número de discos, generalmente ocho, de diámetros diferentes,
ordenados de mayor a menor (el de mayor diámetro abajo). Las otras dos
varillas están vacías. El juego consiste en pasar todos los discos de la
varilla ocupada a una de las varillas libres.

Para llegar a ese objetivo hay que respetar tres reglas:

1. Sólo se puede mover un disco cada vez.


2. Un disco de mayor tamaño no se puede colocar encima de uno más
pequeño.
3. Sólo se puede mover el disco que se encuentre en la parte superior
de cada varilla.

Resolver el juego usando algoritmos recursivos.

&     



 ) *
(c
2010-11-06 17:26:57

ejercicio de fibonacci

http://codepad.org/m3v0fWLz

(c
2010-11-11 00:58:55

/*

* Copypaste(p) by b0ch0n

* Volvamos al problema de los palíndromos.

* Pero ahora usaremos una función recursiva

* para determinar si una cadena determinada es o no palíndroma.

*/

#include <iostream>

using namespace std;

void Palindromo(char palabra[]);

bool pasada=false;

int main()

Palindromo(\"alguna\");

Palindromo(\"salas\");
Palindromo(\"anitAlaValaTina\");

Palindromo(\"cualquiera\");

Palindromo(\"zq\");

Palindromo(\"xx\");

Palindromo(\"dabalearrozalazorraelabad\");

system(\"pause\");

void Palindromo(char palabra[])

char *pPrimero=0; //apuntara al primer caracter

char *pUltimo=0; //apuntara al ultimo caracter

char cadAux[40]=\"\";

int n=0; //nro de caracteres a copiar

int largo=0; //largo de la cadena

bool palindromo=true;

pPrimero=palabra; //apunto al primer caracter

largo=strlen(pPrimero); //obtengo el largo de la palabra

pUltimo=pPrimero+largo-1; //apunto al ultimo caracter

char primerChar;

char ultimoChar;

if(!pasada)

cout<<\"La palabra: \"<<pPrimero;

primerChar=tolower(*pPrimero);
ultimoChar=tolower(*pUltimo);

if(primerChar==ultimoChar)

n=largo-2;//es la cantidad de char a copiar

if(n>0)

pasada=true;

palindromo=true;

strncpy(cadAux,pPrimero+1,n);//pPrimero+1 apunta al segundo char

return Palindromo(cadAux);

else

if(largo>1)

palindromo=false;

if(palindromo)

cout<<\", es palindromo\"<<endl<<endl;

else

cout<<\", no es palindromo\"<<endl<<endl;

pasada=false;

return;

© Septiembre de 2000, Salvador Pozo, salvador@conclase.net

Você também pode gostar