Sie sind auf Seite 1von 10

Repblica bolivariana de Venezuela Ministerio del poder popular para la defensa Universidad nacional experimental politcnica de las fuerzas

armadas Nirgua-nucleo Yaracuy

Recursividad

Profesor: Luis Sequera

Participante: Sergio J. Ramos S. CI: 18.980.145.

La recursividad

Recursividad Primero debemos decir que la recursividad no es una estructura de datos, sino que es una tcnica de programacin que nos permite que un bloque de instrucciones se ejecute n veces. Remplaza en ocasiones a estructuras repetitivas. Este concepto ser de gran utilidad para el captulo de la estructura de datos tipo rbol. La recursividad es un concepto difcil de entender en principio, pero luego de analizar diferentes problemas aparecen puntos comunes. En C# los mtodos pueden llamarse a s mismos. Si dentro de un mtodo existe la llamada a s mismo decimos que el mtodo es recursivo. Cuando un mtodo se llama a s mismo, se asigna espacio en la pila para las nuevas variables locales y parmetros. Al volver de una llamada recursiva, se recuperan de la pila las variables locales y los parmetros antiguos y la ejecucin se reanuda en el punto de la llamada al mtodo.

Se dice que una funcin es recursiva cuando se define en funcin de si misma. No todas la funciones pueden llamarse a si mismas, sino que deben estar diseadas especialmente para que sean recursivas, de otro modo podran conducir a bucles infinitos, o a que el programa termine inadecuadamente. Tampoco todos los lenguajes de programacin permiten usar recursividad. C++ permite la recursividad. Cada vez que se llama a una funcin, se crea un juego de variables locales, de este modo, si la funcin hace una llamada a si misma, se guardan sus variables y parmetros, usando la pila, y la nueva instancia de la funcin trabajar con su propia copia de las variables locales. Cuando esta segunda instancia de la funcin retorna, recupera las variables y los parmetros de la pila y continua la ejecucin en el punto en que haba sido llamada. Por ejemplo: Podramos crear una funcin recursiva para calcular el factorial de un nmero entero. El factorial se simboliza como n!, se lee como "n factorial", y la definicin es: n! = n * (n-1) * (n-2) *... * 1 Hay algunas limitaciones:

No es posible calcular el factorial de nmeros negativos, no est definido. El factorial de cero es 1.

La recursividad

De modo que una funcin bien hecha para clculo de factoriales debera incluir un control para esos casos:
/* Funcin recursiva para clculo de factoriales */ int factorial(int n) { if(n < 0) return 0; else if(n > 1) return n*factorial(n-1); /* Recursividad */ return 1; /* Condicin de terminacin, n == 1 */ }

Veamos paso a paso, lo que pasa cuando se ejecuta esta funcin, 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 funcin factorial es un buen ejemplo para demostrar cmo funciona una funcin recursiva, la recursividad no es un buen modo de resolver esta funcin, que sera ms sencilla y rpida con un simple bucle for. La recursividad consume muchos recursos de memoria y tiempo de ejecucin, 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.

La recursividad

#include <iostream> using namespace std; /* Prototipo de funcin */ void Permutaciones(char *, int l=0); int main(int argc, char *argv[]) { char palabra[] = "ABCDE"; Permutaciones(palabra); cin.get(); 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 cout << 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 posicin, es decir, pueden permutar su posicin con otro. No se fija ningn elemento de la lista, l = 0: Permutaciones (cad, 0)
0 A 1 B 2 C 3 D 4 /0

Se llama recursivamente a la funcin, pero dejando fijo el primer elemento, el 0: Permutacin (cad,1)
0 A 1 B 2 C 3 D 4 /0

La recursividad

Se llama recursivamente a la funcin, pero fijando el segundo elemento, el 1: Permutacin (cad,2)


0 A 1 B 2 C 3 D 4 /0

Ahora slo quedan dos elementos permutables, as que imprimimos sta permutacin, e intercambiamos los elementos: l y l+i+1, es decir el 2 y el 3.
0 A 1 B 2 D 3 C 4 /0

Imprimimos sta permutacin, e intercambiamos los elementos l y l+i+1, es decir el 2 y el 4.


0 A 1 B 2 /0 3 C 4 D

En el caso particular de que l+i+1 sea justo el nmero de elementos hay que mover hacia la izquierda los elementos desde la posicin l+1 a la posicin l:
0 A 1 B 2 C 3 D 4 /0

En este punto abandonamos el ltimo nivel de recursin, y retomamos en el valor de l=1 e i = 0.


0 A 1 B 2 C 3 D 4 /0

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


0 A 1 C 2 B 3 D 4 /0

En la siguiente iteracin del bucle i = 1, llamamos recursivamente con l = 2: Permutaciones (cad,2)

La recursividad

0 A

1 C

2 B

3 D

4 /0

Imprimimos la permutacin e intercambiamos los elementos 2 y 3.


0 A 1 C 2 D 3 B 4 /0

Y as sucesivamente. Otras formas de recursividad Existen otras formas de implementar algoritmos recursivos, no es necesario que una funcin se invoque a si misma. Por ejemplo, un par de funciones A y B pueden crear un algoritmo recursivo si la funcin A invoca a la funcin B, y esta a su vez invoca a la funcin A. Este mismo mecanismo se puede implementar con tres, cuatro o con cualquier nmero 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 disear un procedimiento recursivo para calcular la suma de los n primeros elementos de la serie, de modo que usemos una funcin 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 std; double par(int); double impar(int); double suma(int); int main() { cout << suma(3) << endl; cout << suma(13) << endl; cout << suma(23) << endl; cout << suma(87) << endl; cout << suma(250) << endl; cout << suma(450) << endl; return 0; }

La recursividad

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); }

Escriba una funcin recursiva para calcular la potencia de exponente entero de un nmero. Pruebe la funcin en un programa C++. Recuerde que an =a * an-1

#include <iostream> using namespace std; long pot(int x, int y); int main(int argc, char *argv[]) { int base, exp, ress; cout<<"ingrese base: "; cin>>base; cout<<"ingrese exponente: "; cin>>exp; ress= pot(base, exp); cout<<ress; return 0; } long pot(int x, int y){ if (y==0){ return(1); }else{ return(x*pot(x,y-1)); } }

La recursividad

Sacar races cuadradas aproximadas

El programa utiliza Funciones Recursivas para dar una raz cuadrada entera de un nmero (ingresado por el usuario). Por ende se ingresa un nmero (a) junto con una variable que resta continuamente (b) y un contador (c). Cuando estas variables entran en la funcin recursiva, el numero ingresado es restado continuamente con la variable b y el contador aumenta en uno. El dato importante en esta lgica es el contador ( c) quien nos proporciona la raiz aproximada entera #include <stdio.h> int funcion(int a, int b,int contador){ //Funcion recursiva que busca raices aproximadas //-------------Simbologia------------//a= Variable local representante del numero ingresado por el usuario //b= Representante de b=1 en la funcion global. Este valor local Resta continuamente el numero... //...hasta que sea menor o igual a cero. Es notable mencionarque b no es constante y aumenta en el numero //...no es cero //c= Representante de c=0 en la funcion global.El contador aumenta con cada resta realizada por "b"... //...su valor es la "raiz cuadrada aproximada en este ejercicio" if(a==0 || a<0) //Si el numero ingresado por el usuario es menor o igual a cero. Se retorna el contador (la raiz cuadrada aproximada) return contador; else //De lo contrario: contador++; //El contador aumenta return funcion((a-b),(b+2),contador); //Junto con llamar nuevamente a la funcion. //Notese que en esta nueva funcion entra "El numero restado con la cifra b" y con b redefinido y aumentado en dos } main(){ int a,b=1,c=0; //a= El numero ingresado por el usuario //b= Globalmente se declara como uno y no tiene un papel mas protagonico mas que entrar en una funcion...

La recursividad

//...localmente se utiliza para restar continuamente el valor ingresado por el usuario //c= Globalmente se declara como cero y no tiene un papel mas protagonico mas que entrar en una funcion... //...localmente es usado como un "contador" en la funcion en la cual aumenta cada vez que se le resta //...el valor "b" al numero del usuario. printf("Raices aproximadas"); printf("Ingrese un numero positivo: "); scanf("%d",&a); //Usuario ingresa el numero if(a>=0){ //Caso correcto: El usuario ingreso un numero positivo funcion(a,b,c); //Los numeros ingresan a la duncion: el numero del usuario,la variable b y la variable c printf("\nLa raiz aproximada de %d es %d... ",a,funcion(a,b,c)); }else{ //Caso incorrecto: Se ingreso un numero negativo printf("Error: Se ingreso un numero negativo\n"); } return 0; //Salida exitosa }

La funcin Repetir es recursiva porque dentro de la funcin se llama a s misma. Cuando ejecuta este programa se bloquear y generar un error. Analicemos como funciona: Primero se ejecuta la funcin Main, luego de crear un objeto llamamos a la funcin Repetir.Hay que tener en cuenta que cada vez que se llama a una funcin se reservan 4 bytes de la memoria que se liberarn cuando finalice su ejecucin. La primera lnea de la funcin llama a la funcin Repetir, es decir que se reservan 4 bytes nuevamente. Se ejecuta nuevamente una instancia de la funcin Repetir y as sucesivamente hasta que la pila esttica se colme y se cuelgue el programa.
Programa:
using using using using System; System.Collections.Generic; System.Linq; System.Text;

namespace Recursividad1 { public class Recursividad { void Repetir() { Repetir(); } static void Main(string[] args)

La recursividad

{ Recursividad re = new Recursividad(); re.Repetir(); } } }

La recursividad