cap2.2 recursividad

41
Ing. Mary Dunnia López Ing. Mary Lopez RECURSIVIDAD Programacion II Iterar es Humano Recursividad es Divino Universidad Autónoma Gabriel Rene Moreno FICCT Semestre I/2015

Upload: mary-lopez

Post on 25-Jul-2015

529 views

Category:

Education


1 download

TRANSCRIPT

Ing. Mary Lopez

RECURSIVIDADProgramacion II

Iterar es Humano Recursividad es Divino

Universidad Autónoma Gabriel Rene MorenoFICCT

Semestre I/2015

Ing. Mary Dunnia López

Contenido

Introducción1

Principios de la Inducción Completa2

Estrategias para Procesos Recusivos3

Ejercicios4

1. INTRODUCCION

Ing. Mary Dunnia López

Definición- Es una Técnica

que permite que una función se llame a si misma.

Recursividad

Definition- Un algoritmo es recursivo si al estar encapsulado en una función es llamado desde la misma función por lo menos 1 vez.

Recursión va ligado a repetición

Ing. Mary Dunnia López

1.1 Validez del algoritmo recursivo

Caso Base• Evita que el

algoritmo sea infinito.

• El problema puede resolverse sin tener que hacer uso una nueva llamada a si mismo.

Al menos 2 elementos

Paso Recursivo Relaciona el

resultado del algoritmo en base a los resultados de casos mas simples.

Se hacen llamadas a la misma función pero cada vez mas próximas al caso base.

Ing. Mary Dunnia López

1.2 Utilidad de la Recursividad

Un Funcion se llama a si misma

Codificación simple y corta

Existe una sobrecarga

asociada con las llamadas a sub algoritmos

Algoritmo Recursivo

Por que usar ?

Ing. Mary Dunnia López

1.3 ¿Cuándo usar recursividad?

Es una técnica potente de programación que permite resolver

problemas complejos en forma simple elegante y clara.

Sin Embargo: Sera la ultima solución a intentar en caso que los procesos

iterativos no funcionen.

El uso de recursividad únicamente cuando no haya solución iterativa.

Si analizamos en el caso factorial Por Recursividad: Se tiene que almacenar datos y direcciones

en la pila del programa. Por Iteración: se almacenan 2 datos nada mas.

Existen algoritmos complejos se codifican mas fácil mediante métodos recursivos.

RECURSIVO:

Int Factorial (int n ){If (n==0) return (1);Return (n*Factorial (n-1));}

ITERATIVO:

Int Factorial (int n ){Int ¡, res = 1;For(¡=1;¡<=n;¡++ ) res = res*¡;return (res);}

Ing. Mary Dunnia López

1.4 Tipos de recursividad

Simple Si cumple que tiene una sola llama a si misma. Se lo puede convertir en algoritmo iterativo. Por ejemplo: El factorial.

Multiple --> Varias llamadas a si misma por ejemplo: Fibonacci

Anidada --> Es cuando alguna llamada recursiva recibe como parámetro a una llamada recursiva, su complejidad en término de llamadas recursivas resultará mucho más difícil de calcular

Cruzada --> son algoritmos donde una función provoca una llamada a si misma de forma indirecta, a través de otras funciones.

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

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

2. Principio de la inducción completa

Ing. Mary Dunnia López

La caída de dominós en cadena ilustra la idea del principio de inducción: si el primer domino cae, y si cualquiera al caer hace caer al siguiente, entonces todos caen. (Tomado del libro \Discrete mathematics" de K. Rosen)

Para entender recursividad se debe conocer un poco de los tipos inductivos, aplicando la inducción matemática.

Un tipo inductivo es aquel que tiene una cantidad variable de elementos, y que si cierta condición se cumple para un elemento, entonces es posible demostrar que se cumple para todos los demás.

Si en una fila muy larga de personas alguien dice un secreto a otra esta automáticamente se lo dice a la persona que está a lado de ella.

¿Se enterarán entonces todas las personas de la fila del secreto contado? Una primer persona se lo dice a la segunda, esta al recibir el mensaje se lo dice

a la tercera, esta se lo dirá a la cuarta y así sucesivamente hasta llegar al final de la fila. Luego la propiedad se cumple para todos los que estén en la fila.

El principio de inducción completa parte de un esquema proposicional

¿ Qué es esquema proporcional ?

Ing. Mary Dunnia López

Una proposición es una oración de la que se puede decir que es falso o verdadero.

En esta oración figura una variable, la cual al ser reemplazada por un

valor de su dominio la convierten en una proposición:

P1[x] = “Dos es mayor que x", x E {1,2,3,4}P2[n] = n < 2 , n E {3,4,5,6,7}

P3[n] = “La suma de los primeros n números naturales es igual al producto de N por su sucesor dividido entre dos", n E |N

P4[n] = 1+2+3+…+n= n*(n+1)/2, n E |N

2.1 Esquema proposicional

Ing. Mary Dunnia López

2.2 El primer PIC

Sea P[n] un esquema proposicional sobre los Naturales, se puede demostrar que P[n] es válido si se logramos probar que: P[1] es verdadero Es el primer valor del dominio Suponiendo que P[n-1] (hipótesis) es verdadero Todas las

proposiciones menos una. La penúltima proposición Probar que P[n] también es verdadero

Caso Base. Es el proceso para el primer valor de la variable de recursión. Por lo general, está representado por la forma nula o vacía del tipo de datos. Si se trabaja con una lista encadenada, un caso base sería la lista vacía.

• Debe ser la nada, lo vacío, lo nulo 0• Algún otro número 1

Caso General Es el proceso que hace lo que se necesita, por lo que se lo utiliza pero con un valor menos (P[n-1]).

Ing. Mary Dunnia López

2.3 El Segundo PIC en recursión

Caso Base. Debe resolver el problema para los primeros m valores del dominio de la variable de recursión.

Caso General Es el proceso hace lo que se necesita, pero lo hace para K (P[k]) , usando éste proceso debe hacer que funcione para N (P[n]).

• Para k=n-1 M=1 (se necesita mínimo un caso base)• Para k=n-2 M=2 (se necesita al menos 2 casos base)

Sea P[n] un esquema proposicional sobre los Naturales, se puede demostrar que P[n] es válido si se puede probar que:

a) P[1]^P[2] ^.. ^P[m] Es verdadero

b) Suponiendo P[k] (hipótesis) Es verdadero. Donde m<k<n

c) Probar que P[n] también lo es.

3. Estrategias para procesosRecursivos

Dos estrategias de resolución de problemas recursivos: Divide y vencerás : Divide el problema de tamaño n en problemas más

pequeños cada uno de los cuales es similar al original pero de menor tamaño.

• Si se llega a una solución de los sub-problemas, se podrá construir de forma sencilla una solución al problema general.

• Cada uno de esos sub-problemas se podrá resolver de forma directa (caso base) o dividiéndolos en problemas más pequeños mediante la recursividad.

Backtracking = Fuerza Bruta = Vuelta Atras. Divide la solución en pasos, en cada uno de los cuales hay una serie de opciones que ha que probar de forma sistemática. En cada paso se busca una posibilidad o solución o solución aceptable.

• Si se encuentra se una solución valida pasa a decidir el paso siguiente.• Si no se encuentra una solución aceptable, se retrocede hasta la última solución

aceptable encontrada y se elige una opción distinta a la anterior. La recursividad se utiliza para poder retroceder hasta encontrar una solución aceptable.

• Ejemplos: Juegos de tablero, laberintos, etc.

Ing. Mary Dunnia López

3.1 Definición de Procesos Recursivos

1. ¿Cuál es la variable de recursión? Es lo primero que hay que identificar Indica cuantas veces se repite la acción principal del proceso.

2. ¿Cuál es el dominio de la variable de recursión?

• El conjunto de números naturales de 0 a N.

3. Caso Base Resolver el problema para el primer valor del dominio de la variable de recursión (Definido en el Paso 2)

4. Paso Recursivo Si ya existe un proceso que hace lo que se necesita, en este paso se lo LLAMA disminuyendo o aumentado el numero de

elementos N para que se acerque al CASO BASE. Este paso debe completar lo que falte.

Ing. Mary Dunnia López

3.2 Resolución de Procesos Recursivos

Resolución de problemas recursivos. Para hallar la solución recursiva a un problema podemos hacernos tres preguntas:

1. ¿Cómo se puede definir el problema en términos de uno o más ?• Problemas más pequeños del mismo tipo que el original.

2. ¿Qué instancias del problema harán de caso base?• Conforme el problema se reduce de tamaño, se alcanzará el caso base

3. ¿Cómo se usa la solución del caso base para construir una solución• Alcanzado el caso base, determinar como ahora lograr la solución

final.

Ing. Mary Dunnia López

3.3 Pasos para crear un AR

Escriba un «IF»

a. caso Base Donde la función no se llama a si misma.Simple = No se necesita llamada recursiva (no hay repetición) Tal vez deba almacenar el resultado en una variable.Escriba un «ELSE»

b. Paso Recursivo Donde la función se llama a si mismaEs la próxima entrada/estado

Esta deberá aproximarse cada vez mas al caso base

Asuma que la llamada recursiva funciona:

a. Pregúntese que hace el algoritmo?

b. Pregúntese como ayuda en la solución del problema ?

Ing. Mary Dunnia López

3.1.4 Base Para escribir el AR

IF (pregunta por el caso base) { //Caso Base

} else {

// Paso Recursivo

}

Ing. Mary Dunnia López

Ejemplo 1: Factorial Recursivo

Definición recurrente de la función factorial n!

Si n=0 1 Caso Base

N! =

Si n>=1 n*(n-1)! Paso recursivo

3! = 3 · (3-1)! = 3 · 2! = 3 · 2 · (2-1)! = 3 · 2 · 1! = 3 · 2 · 1 · (1-1)! = 3 · 2 · 1 · 0! = 3 · 2 · 1 · 1 = 6

Ing. Mary Dunnia López

Ejemplo 1: Factorial Recursivo

ITERATIVO:

Int Factorial (int n ){Int ¡, res = 1;For(¡=1;¡<=n;¡++ ) res = res*¡;return (res);}

RECURSIVO:

Int Factorial (int n ){If (n==0) return (1);Return (n*Factorial (n-1));}

Conclusión: un programa recursivo puede ser menos eficiente que unoiterativo en cuanto a uso de memoria y velocidad de ejecución.

N es 3

FACTORIAL 3* FACTORIAL (2)

Retorno 6

N es 2

FACTORIAL 2* FACTORIAL (1)

Retorno 2

N es 1

FACTORIAL 1* FACTORIAL (0)

Retorno 1

N es 0

FACTORIAL 1

Retorno 1

FACT FACTORIAL (3)

Ciclo del Factorial Recursivo

Ing. Mary Dunnia López

void ConBin(TStringGrid *Grid,int n,int i,int &j){

int a;

if(n==0) {

Grid->ColCount=i;

j=0;

} else{

ConBin(Grid,(n/2),i+1,j);

Grid->Cells[j][0]=n%2;

j=j+1; }

}

Conversión de un numero en base 10 a sistema Binario.

Ejemplo 2: Convertir a Binario

void GetBin(TStringGrid *Grid,int num){ int j=0; ConBin(Grid,num,0,j);}

Ing. Mary Dunnia López

1. ¿Cómo se puede definir el problema en términos de más problemas?

En una lista de N elementos, se realiza la búsqueda entre los elementos de la izquierda, si el elemento es menor que el central, o de la derecha, si el elemento es mayor que el central.

2. ¿Qué instancias del problema harán de caso base?- Cuando se encuentra el elemento Este es igual que el

elemento central de la lista.

3. ¿Qué instancias del problema harán de caso base?Llegar a una lista de un único componente.

Si el elemento central es el buscado, el elemento está en la posición central.Si el elemento central no es el buscado, el elemento no está.

Conforme el problema se reduce de tamaño. Se alcanzará el caso base.

En cada paso se va reduciendo la lista, al elegir la parte izquierda o la parte derecha. Llegará un momento en que se pueda llegar a buscar el elemento en una lista de un único componente.

Ejemplo 3: Convertir a Binario

Ing. Mary Dunnia López

Ejemplo 3: Búsqueda Binaria

void busq_bin(int inicio, int final, vector <int> &cadena, int x) {

bool flag = false; int medio;

while((inicio <= final) && (! flag)) {

medio = (inicio + final) / 2;

if (x > cadena[medio]) inicio = medio + 1;

else if(x < cadena[medio]) final = medio - 1;

else flag = true;

}

if(flag)

cout << "Elemento encontrado en la posicion " << medio << endl;

else cout << "El elemento no esta en la lista" << endl;

}

Ing. Mary Dunnia López

Ejemplo 3: Busqueda Binaria

bool busqbin(int cadena[], int inicio, int final, int x){

static bool flag; bool res; if(inicio > final)

return false; else {

int m = (inicio + final)/2; if(x < cadena[m]) res = busqbin(cadena, inicio, m-1, x); else if(x > cadena[m]) res = busqbin(cadena, m+1, final, x); else flag = true;

} return flag; } /*Nota: Si se encuentra devuelve true, sino false*/

4. Ejercicios

Ing. Mary Dunnia López

Ejercicio 1: Numeros

int ConvBin(Cardinal num){ int res=0;

if (num==0) {res=0;}else{

res=res+ConvBin(num/2)*10 + num%2;}return res;

}

Convertir a binario• Caso base Si el numero a convertir es cero retonra cero

• Paso Recursivo Si es mayor que cero intenta operaciones

ConvBin(num/2)*10 + num%2

Ing. Mary Dunnia López

Ejercicio 2: Cadenas

String InvCad(String cad){ String res; if(cad.Length()==1){ return cad; }else{ res=InvCad(cad.SubString(1,cad.Length()-1)); res=cad.LastChar()+res; return res; }}

Invertir una cadena• Caso base si la longitud de la cadena es 1 retorna la cadena

• Paso Recursivo Si es mayor que 1, se intenta seguir retrocediendo hasta el

Primer caracter. Para luego al devolver la pila ir concatenando cada caracter

Ing. Mary Dunnia López

Serie de Fibonacci.• Sucesión de números naturales en la que a partir del término 2 de la serie, cada número

(número de Fibonacci) es la suma de los dos anteriores:

0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, …• El problema de calcular el número n de la serie se puede resolver de forma iterativa.

Ejercicio 3: Fibonacci

void main()

{

using namespace std;

double a, b, c;

a=0;

b=1;

cout<<"The Fibonacci Sequence!"<<endl<<endl;

cout<<a<<"\t"<<b<<"\t";

for(int count = 3; count<=20; count++) {

c=a+b;

cout<<c<<"\t";

a=b;

b=c;

if(count % 5 == 0)

cout<<endl;

}

}

Ing. Mary Dunnia López

Serie de Fibonacci. recursiva El problema del cálculo del número n de la serie de. Fibonacci también admite una

definición recursiva. Si n = 0 , Fibn = 0 Si n = 1, Fibn = 1 Si n > 1 , Fibn = Fibn-1 +

Fibn-2.

int fibonaci(int num){

if(num<3){

return 1;

}else{

int x=fibonaci(num-1);

int y=fibonaci(num-2);

return x+y;

}

}

String num=InputBox("Enesimo termino Serie Fibonaci","Itroduzca un numero",0);

int val=StrToInt(num);

int res=fibonaci(val);

ShowMessage(res);

Ejercicio 3: Fibonacci

Ing. Mary Dunnia López

Ejercicio 3: Fibonacci Vent-Desv

• Para la llamada Fibonacci(5) el número de llamadas a realizar sería de 15.• Un algoritmo iterativo con variables locales que almacenaran los cálculos

parciales sería más eficiente.

• Sólo necesitaría n iteraciones para calcular Fibonacci(n)

Ing. Mary Dunnia López

Ejercicio 3: Fibonacci Complejidad

Luego que tan ineficiente es el algoritmo ?La figura anterior lo muetra

Para fib(n) el algoritmo computa FOR 0<=n<=6

N Numero de veces que computa

 

0 1   1

1 1 1

2 3 Fib(0) + Fib(1)  3 > 2 ≈ 2^2/2

3 5 Fib(1) + Fib(2)  5 > 2.8323 ≈ 2^3/2

4 9 Fib(2) + Fib(3)  9 > 4 ≈ 2^4/2

5 15  Fib(3) + Fib(4) 15 > 5.65 ≈ 2^5/2

6 25 Fib(4) + Fib(5) 25 > 8 ≈ 2^6/2

OBSERVAR QUE PARA obtener el Fib(6)

Fib(6) Fib(4) + Fib(5) +1 1 por la RAIZ de los nodos

Ing. Mary Dunnia López

Fn=fn-1 + fn-2 PARA n>=2

El analisis muestraF0=0F1=1

Calculando los primero términos se tieneF2=f1+f0=1+0=1F3=f2+f1=1+1=2F4=f3+f2=2+1=3F5=f4+f3=3+2=5, etc.

• La siguiente figura muestra el porque es ineficiente ? Para calcular Fib(5) 15NODOS?

• El hijo de un nodo en el arbol contiene las llamadas recursivas realizadas ,hechas por la llamada al NODO. Ver figura.

Ejercicio 3: Fibonacci Complejidad

Ing. Mary Dunnia López

El numero de elementos en el árbol se mas que duplica cada que N incrementa por 2

Por ejemplo para n=4 --> 9 llamadasPor ejemplo para n=6 --> 25 llamadasPara N --> F(n) llamadas

Pero que tan rapido crece la serie fibonacci ?Si F(n)=F(n-1) + F(n-2)Si Calcularemos las raíces de la ecuación característica asociada a la ecuación en recurrencia

X^2 = x + 1Luego x^2 – x -1 =0Una de ellas, es el llamado número de oro (Golden Ratio), cuyo valor aproximado es 1.61803 y su valor exacto es c = (1+√5)/2.De esta forma c2 = c + 1 Luego cn = cn-1 + cn-2

Ejercicio 3: Fibonacci Complejidad

Ing. Mary Dunnia López

Es decir, la progresión geométrica {cn} satisface la misma ecuación en recurrencia que la función de Fibonacci F(n) = F(n-1) + F(n-2). Ahora, por inducciónComo, c0 = 1 = F(2), c = c1 < 2 = F(3). obtenemos que cn-2 < F(n)

F(N)> 2n/2

Ejercicio 3: Fibonacci Complejidad

Ing. Mary Dunnia López

Ejercicio 4 : Vectores

Convertir un numero Entero a Binario.

void ConBin(TStringGrid *Grid,int n,int i,int &j){ int a; if(n==0) { Grid->ColCount=i;

j=0; } else{

ConBin(Grid,(n/2),i+1,j); Grid->Cells[j][0]=n%2; j=j+1; }

}

void GetBin(TStringGrid *Grid,int num){ int j=0; ConBin(Grid,num,0,j);

}

Ing. Mary Dunnia López

Ejercicio 5 : Matrices

void __fastcall TForm1::Rizo1Click(TObject *Sender){ int num=StrToInt(InputBox("Matriz 1","Introduzca Nro. de filas y columnas","1" )) ;

LimpGrid(true,num,num);

int mfil=num-1; int mcol=0;

MatrizS5(Grid1,0,0,mfil,mcol);}

Generar la siguiente matriz

void MatrizS5(TStringGrid *Grid,int posf,int posc,int &max,int &min){if ( posc>max) { posc=min; posf=posf+1;}if(posf>max){

max=max-1;min=min+1;posf=min;posc=min; }

if(min<max+1){ if(posf==max || posf==min || posc==max || posc==min) Grid->Cells[posc][posf] =max+1; if(posf==max || posf==min) posc=posc+1; else if(posc==min)posc=max; else posc=posc+1; MatrizS5(Grid,posf,posc,max,min);}}

Ing. Mary Dunnia López

Para entender la recursividad, primero se ha de entender la recursividad.

(anónimo)