You are on page 1of 98

TEMA 2.

RECURSIVIDAD

Recursividad. Introduccin

Recursividad. Introduccin
3

En

un p programa g una funcin f() () p puede llamar a otra g(). f() y g() llamarse a s mismas?

Pueden

Recursividad. Introduccin
4

F d Fundamentacin i matemtica i
Mtodo
Se

de induccin en el conjunto de los nmeros naturales:


demuestra la certeza para un cierto valor k de N Se verifica que se cumple para (k+1) Se concluye que es cierto para cualquier valor de N

El problema queda resuelto

Recursividad. Introduccin
5

La recursividad L i id d consiste i t en realizar li una definicin d fi i i d de un concepto en trminos del propio concepto que se est definiendo. Ejemplos:

Los nmeros naturales se pueden definir de la siguiente forma: 0 es un Nmero natural y el sucesor de un nmero natural es tambin un nmero natural. El factorial de un nmero natural n, es 1 si dicho nmero es 0, o n multiplicado por el factorial del nmero n-1, n 1 en caso contrario. contrario La n-sima potencia de un nmero x, es 1 si n es igual a 0, o el producto de x por la potencia (n-1)-sima de x, cuando n es mayor que 0. 0

En todos estos ejemplos se utiliza el concepto definido en la propia p p definicin.

Recursividad. Introduccin
6

S l i d Solucin de problemas bl recursivos: i


Divisin sucesiva del problema original en uno o varios ms pequeos, del mismo tipo que el inicial. Se van resolviendo estos problemas ms sencillos. sencillos Con las soluciones de stos se construyen las soluciones de los problemas ms complejos. Un problema P se puede resolver conociendo la solucin de otro problema Q que es del mismo tipo que P, pero ms pequeo. Igualmente, supongamos que pudiramos resolver Q mediante la bsqueda de la solucin de otro nuevo problema, R, que sigue siendo del mismo tipo que Q y P, pero de un tamao menor que ambos. Si el problema R fuera tan simple que su solucin es obvia o directa, entonces, d d que sabemos dado b la l solucin l i de d R, R procederamos d a resolver l Q y, una vez resuelto, finalmente se obtendra la solucin definitiva al primer problema, P.

O lo que es lo mismo, mismo una Definicin intuitiva sera:


1. 2.

3.

Recursividad. Introduccin
7

Ejemplos
A.

simples de recursividad.

Clculo del factorial de un nmero, por ejemplo, 5.


5! = 5 * 4! 4! = 4 * 3! 3!= 3 * 2! 2! = 2 * 1! 1! = 1 * 0! Descomposicin del problema en otros ms simples

0! = 1 Solucin Conocida 1! = 1 * 0! = 1 2! = 2 * 1! = 2 3! = 3 * 2! = 6 4! = 4 * 3! = 24 5! = 5 * 4! = 120 Resolucin de problemas complejos a partir de otros ms simples

Recursividad. Introduccin
8

Caractersticas C t ti
1 1.

de d los l problemas bl que pueden d ser resueltos de manera recursiva:


Los problemas pueden ser redefinidos en trminos de uno o ms subproblemas, idnticos en naturaleza al problema original, pero de alguna forma menores en tamao. Uno o ms subproblemas s bproblemas tienen solucin sol cin directa o conocida, no recursiva. Aplicando la redefinicin del problema en trminos de problemas ms pequeos, dicho problema se reduce sucesivamente a los subproblemas cuyas soluciones se conocen directamente. La solucin a los problemas ms simples se utiliza para construir la solucin al problema inicial.

2 2. 3.

4.

Recursividad. Diseo
9

Mdulo Md l

M con una llamada ll d a s mismo: i mdulo d l recursivo directo. Mdulo M con una llamada a otro F F, que hace una llamada a M: Mdulo recursivo indirecto. Ejemplo: j p Implementacin p del factorial de un nmero. public long factorial (long n) { if (n == 0) return 1; else return n * factorial(n-1); }

Recursividad. Diseo
10

Dos D
1. 2.

partes t principales: i i l
La llamada recursiva, que expresa el problema original en trminos de otro ms pequeo. p q El valor para el cual se conoce una solucin no recursiva. Caso base: una instancia del problema cuya solucin no requiere de llamadas recursivas. recursivas

El

caso base:

Acta como condicin de finalizacin de la funcin recursiva. Sin el caso base la rutina recursiva se llamara indefinidamente y no finalizara nunca. Es el cimiento sobre el cual se construir la solucin completa al problema.

Recursividad. Diseo
11

Ejemplo:

Traza del factorial f de 5.

Recursividad. Diseo
12

Bsqueda

de soluciones recursivas: cuatro preguntas

bsicas.
1.

2. 3.

4.

Cmo se puede definir el problema en trminos de uno o ms problemas ms pequeos del mismo tipo que el original? Qu instancias del problema harn de caso base? Conforme el problema se reduce de tamao se alcanzar el caso base? Cmo se usa la solucin del caso base para construir una solucin correcta al problema original?

Recursividad. Diseo. Fibonacci


13

Ej Ejemplo: l la l sucesin i de d Fibonacci. Fib i 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ... El tercer trmino de la sucesin se obtiene sumando el segundo y el primero. El cuarto, a partir de la suma del tercero y el segundo. El problema: calcular el valor del n-simo trmino de la solucin, que se obtendr sumando los trminos n-1 y n-2. Las respuestas a la preguntas anteriores seran:
1. 2. 3.
4.

fibonacci(n) = fibonacci(n-1) + fibonacci(n-2). Casos bases: fibonacci(1) ( ) = 1 y fibonacci(2)=1. ( ) En cada llamada a la rutina fibonacci se reduce el tamao del problema en uno o en dos, por lo que siempre se alcanzar uno de los dos casos bases.
fibonacci(3) = fibonacci(2) + fibonacci(1) = 1 + 1.

Se construye la solucin del problema n==2 a partir de los dos casos bases.

Recursividad. Diseo. Fibonacci


14

int fibonacci(int n) { if ((n == 1) || (n == 2)) return 1; else return et n (fibonacci(n-2) (fibonacci(n 2) + fibonacci(n-1)); fibonacci(n 1)) } Peculiaridades de esta funcin recursiva: ms de un caso base y ms de una llamada recursiva (recursin no lineal).

Recursividad. Diseo. Fibonacci


15

Ejemplo: Traza de la funcin f de Fibonacci de 4.

16

Diseo. MCD

Recursividad. Diseo. MCD


17

Ejemplo: mximo comn divisor de dos nmeros m y n. Ejemplo de problema en el que la solucin al encontrar el caso base es la propia solucin del problema.
Solucin:

Algoritmo de Euclides:
si n>m, , MCD(n, ( , m)=MCD(m,n%m) ) ( , )

Algoritmo de Euclides: Si n divide a m, Entonces MCD(m, n)=n, Si no, MCD(m, n) = MCD(n, m % n),

Recursividad. Diseo. MCD


18

S l i Soluciones al las cuatro t preguntas: t


1.

Es evidente que MCD(m, n) ha sido definida en trminos de un problema del mismo tipo, pero justifiquemos que MCD(n, m % n) es de tamao menor que MCD (m, (m n): n)

El rango de m % n es 0, ..., n-1, por tanto el resto es siempre menor que n. Si m > n, entonces MCD(n, m % n) es menor que MCD(m, n). Si n > m, , el resto de dividir m entre n es m, ,p por lo q que la primera p llamada recursiva es MCD(n, m mod n) es equivalente a MCD(n, m), lo que tiene el efecto de intercambiar los argumentos y producir el caso anterior.

2. 3. 4 4.

Si n divide a m, si y slo si, m mod n = 0, en cuyo caso MCD(m, n) = n, por tanto, tanto se conseguir el caso base cuando el resto sea cero. cero Se alcanzar el caso base ya que n se hace ms pequeo en cada llamada y adems se cumple que 0 m mod n n-1. En este caso, caso cuando se llega al caso base es cuando se obtiene la solucin final al problema, por tanto no se construye la solucin general en base a soluciones de problemas ms simples.

Recursividad. Diseo. MCD


19

Ejemplo: Ej l Traza T de d la l funcin f i mximo i comn divisor di i de d d dos nmeros 1440 y 408.

mcd(1440, ( 408) ) mcd(408, 216) mcd(216 24) mcd(216, mcd(192, 24) mcd(24, 0) return 24 return 24 return 24 return 24 return 24

Problema inicial P Problema reducido Q Problema base R

Recursividad. Diseo. MCD


20

Ejemplo:

mximo comn divisor de dos nmeros m y

n.
public int mcd (int m, int n) { if (m % n == 0) return n; else l return t ( d( m % n)); (mcd(n, )) }

21

Diseo. Conteo

Recursividad. Diseo. Conteo


22

Ejemplo: Ej l conteo t de d ocurrencias i de d un valor l en un vector. t Dado un vector de n enteros, el problema a resolver recursivamente consiste en contar el nmero de veces que un valor dado aparece en dicho vector. vector Respuestas:
1.

2. 3. 4.

Si el primer elemento = valor buscado, entonces la solucin ser 1ms el nmero de veces que aparece dicho valor en el resto del vector vector. Si no, no la solucin al problema original ser el nmero de veces que el valor se encuentra en las posiciones restantes El vector a est vaco ocurrencias en el vector= 0. Cada llamada recursiva se reduce en uno el tamao del vector, por lo que nos aseguramos que en N llamadas habremos alcanzado el caso base. Cuando se encuentra una coincidencia se suma uno al valor devuelto por otra llamada recursiva. El retorno del control de las sucesivas llamadas comenzar inicialmente sumando 0 cuando nos hayamos salido de las dimensiones del vector.

Recursividad. Diseo. Conteo


23

Funcin F en Java J que implementa l la l solucin l recursiva, parmetros:


El propio vector (vector). (vector) El valor a buscar (objetivo). El ndice del p primer elemento del vector a procesar p (primero). (p )
public int contarOcurrencias (int[] vector,int objetivo, int primero){ If (primero > vector.length-1) return 0; else{ { if (vector[primero] == objetivo) return(1+contarOcurrencias(vector,objetivo,primero+1)); else return(contarOcurrencias(vector, objetivo, primero+1)); } }

24

Diseo. Combinatoria

Recursividad. Diseo. Combinatoria


25

Ejemplo: Ej l combinaciones bi i sin i repeticin ti i d de n objetos bj t t tomados d d de k en k. Cuntas combinaciones de k elementos se pueden hacer de entre un total de n (combinaciones sin repeticin de n elementos tomados de k en k). Respuestas: R t
1.

El clculo del nmero de combinaciones de n elementos tomados de k en k se puede descomponer en dos problemas:
calcular el nmero de combinaciones de n-1 elementos tomados de k en k. b) el nmero de combinaciones de n-1 elementos tomados de k-1 en k-1.
a)

El

resultado del problema inicial:


ncsr(n, k) = ncsr(n- 1, k-1) + ncsr(n-1, k).

Recursividad. Diseo. Combinatoria


26

n personas y queremos determinar d t i cuntos t grupos de d k personas se pueden formar de entre stas.
4 personas (A, B, C y D), grupos de 2 ncsr(4,2)=ncsr(3,1)+ ncsr(3,2)?

Suma de:

los grupos que se pueden hacer de un tamao k sin contar a la persona A: ncsr(n-1,k) :nmero de grupos que se pueden hacer, de tamao 2, pero sin A ncsr(3,2): {B,C}, {B,D} y {D,C}. l grupos que se puedan los d realizar li incluyendo i l d a esa misma i persona, ncsr(n-1, k-1): ncsr(3,1): {B}, {C} y {D}.(contamos todos los que se pueden hacer con una persona menos y luego le aadimos esa persona). persona)

Solucin final: 3 + 3 = 6

Recursividad. Diseo. Combinatoria


27

2. Casos C
1. 2 2. 3.

b bases:

Si k > n, entonces ncsr(n,k) =0 (no hay elementos suficientes). Si k = 0, 0 entonces este caso slo ocurre una vez (ncsr(n,0)=1). (ncsr(n 0)=1) Si k = n, entonces ncsr(n,n)=1.

3 1 3. 1

llamada recursiva: restamos uno al nmero de elementos elementos, y en la 2, al nmero de elementos y al tamao de la combinacin. 4. Apenas se haya encontrado un caso base, uno de los sumandos tendr un valor. Cuando el otro sumando alcance a un caso base, b se podr d hacer h la l suma y se devolver d l a un valor que ir construyendo la solucin final conforme se produzcan las devoluciones de control.

Recursividad. Diseo. Combinatoria


28

Ejemplo:

combinaciones sin repeticin de n objetos tomados de k en k.


p public int ncsr(int ( n, , int k) ) { if (k > n) return 0; else if (n == k || k == 0) return 1; else return ncsr(n-1, k) + ncsr(n-1, k-1); }

29

Diseo. La Pila del Sistema

30

Recursividad. Diseo. La Pila del Sistema

La memoria L i de d un ordenador d d a la l hora h de d ejecutar j t un programa se divide en dos partes:


la zona donde se almacena el cdigo g del programa p g 2. la zona donde se guardan los datos: pila (utilizada para llamadas recursivas).
1.

Programa principal llama a una rutina M se crea en la pila de un registro de activacin o entorno, E almacena constantes, variables locales y parmetros formales. E t registros Estos i t se apilan il conforme f se llaman ll sucesivamente i t desde d d una funcin f i a otras t Cuando finaliza la ejecucin, se va liberando el espacio

31

Recursividad. Diseo. La Pila del Sistema


Profundidad de la recursin: nmero de registros de activacin en la pila en un momento dado. P bl Problema: S profundidad Si f d d d es muy grande d desbordamiento d b d pila.

32

Recursividad. Diseo. La Pila del Sistema

R Representacin grfica f del d l registro d de Activacin: A

33

Recursividad. Diseo. La Pila del Sistema


Ejemplo Ej l de d evolucin l i de d l la pila: il i impresin i d de palabras l b en sentido contrario al ledo. Parmetros: nmero de palabras que quedan por leer (n). (n)
Se lee la primera palabra, y recursivamente se llama a la funcin para que lea e imprima el resto de palabras, para que finalmente se imprima l la primera leda. l d 2. El caso base: cuando slo quede una palabra (n == 1), en cuyo caso se imprimir p directamente. 3. Como en cada llamada recursiva hay que leer una palabra menos del total, en n-1 llamadas se habr alcanzado el caso base. 4 Una 4. U vez se haya h alcanzado l d el l caso b base al l devolver d l continuamente ti t el control a las funciones invocantes se irn imprimiendo de atrs a delante las palabras obtenidas desde la entrada estndar.
1.

34

Recursividad. Diseo. La Pila del Sistema


public bli void id imp_OrdenInverso(int i Od I (i t n){ ){ String palabra; if ( (n == 1){ ){ palabra =Console.in.readln(); System.out.println(palabra); } else{ palabra =Console.in.readln(); =Console in readln(); imp_OrdenInverso(n-1); System.out.println(palabra); } }

35

Recursividad. Diseo. La Pila del Sistema

Ejemplo de evolucin de la pila: impresin de palabras en sentido contrario al ledo.

36

Recursividad. Diseo. La Pila del Sistema

Ejemplo de evolucin de la pila: impresin de palabras en sentido contrario al ledo.

37

Casos Base

Recursividad. Casos Base


38

!OJO! Correccin C i d de los l casos b base como forma f de d evitar i una recursin infinita, y por tanto, que la pila se agote: 1 Cada rutina recursiva requiere como mnimo un caso base. 1. base 2. Se debe identificar todos los casos base ya que en caso contrario se puede producir recursin infinita. 3. Los casos bases deben ser correctos: las sentencias ejecutadas cuando se d un caso base deben originar una solucin l i correcta t para una i instancia t i particular ti l d del l problema. En caso contrario, se generar una solucin incorrecta. 4. Hay que asegurarse que cada subproblema est ms cercano a algn caso base.

39

Paso de parmetros

Recursividad. Paso de Parmetros


40

Utilizacin U ili i d de parmetros f formales: l cuidado id d al ld decidir idi si il los parmetros sern de entrada, salida o entrada/salida. Veamos un ejemplo:
public long factorial (Long n) { if (n.longValue() ( l V l () == 0) return 1; else{ n = n - 1; return (n+1) * factorial(n); } }

Qu ocurre cuando se empiezan a devolver las llamadas recursivas? El valor de n siempre ser igual a 0, y se devolver siempre 1 El factorial de cualquier nmero ser 1 (INCORRECTO)

Recursividad. Paso de Parmetros


41

long fact, tamanio= 3; fact= factorial(tamanio); fact fact= factorial(n == 3) (n == 2) * factorial (n == 2) (n == 1) *factorial(n == 1) (n==0)*factorial(n==0) return 1. 1 return (n+1==1) * 1 = 1 (n+1==1) ) * 1= 1 return ( return (n+1==1) * 1= 1 fact= 1

Recursividad. Paso de Parmetros


42

Regla general para decidir si un parmetro ser pasado por copia o por referencia es la siguiente: Si se necesita recordar el valor que tena un parmetro una vez que se ha producido la vuelta atrs de la recursividad, entonces ha de pasarse por valor. En caso contrario, se podr pasar por referencia. public void factorial (long p ( g n){ ){ if (n == 0) return 1; else{ return factorial(n-1)*n; } }

Recursividad. Paso de Parmetros


43

OJO! Cuidado con el nmero y tipo de parmetros formales de una funcin recursiva. S l i Soluciones:
1. 2. 3.

Declarar algunas variables como globales. H Hacer pasos por referencia. f i Crear una funcin y dentro de ella implementar la funcin recursiva (la p ( primera recubrir a la segunda). g )

PARA EVITAR EFECTOS SECUNDARIOS SLO SE PERMITIR LA SEGUNDA DE ESTAS OPCIONES.

Recursividad. Paso de Parmetros


44

Algunas reglas generales para el paso de parmetros: A. Generalmente pasar por copia los parmetros necesarios para determinar d i si i se ha h alcanzado l d el l caso b base. B. Si la rutina acumula valores en alguna variable o vector, sta d b ser pasada debe d por referencia. f i Cualquier C l i cambio bi en dicho di h vector se repercutir en el resto de llamadas recursivas posteriores. C. Los vectores y las estructuras de datos grandes se pasarn por referencia y para p p evitar que q se puedan p modificar de manera errnea, se utilizar la palabra reservada const.

45

Recursividad o Iteracin

Recursividad o Iteracin
46

Cuestiones pendientes de contestar:


Existen

problemas que nicamente puedan ser resueltos mediante iteracin y no con recursividad? Existen problemas que nicamente puedan ser resueltos mediante recursividad y no con iteracin? Qu mtodo utilizar: recursividad o iteracin? Hay casos en los que deba evitarse la recursividad?

Recursividad o Iteracin
47

Problemas de la recursividad: Ineficiencia inherente de algunas g implementaciones recursivas (Fibonacci) Tiempo aadido para gestionar las invocaciones recursivas y correspondientes vueltas atrs Desbordamiento D b d i t de d l la pila il si i la l profundidad f did d en la l convergencia al caso base es muy alta Repeticin innecesaria de pasos ya ejecutados en ciclos previos del proceso de recursin

Recursividad o Iteracin
48

Por qu usar entonces la l recursin? ? 1. Para multitud de problemas resulta ms fcil e i t iti encontrar un solucin intuitivo l i recursiva. i Ad Adems sta suele ser ms elegante y fcilmente comprensible que su versin iterativa 2. La eficiencia de una implementacin recursiva puede mejorarse a travs de tcnicas como la programacin dinmica 3. Encontrada una solucin recursiva, en ltimo trmino siempre es posible transformarla en iterativa, en algunos casos de forma trivial y mecnica

Recursividad o Iteracin
49

La propia L i definicin d fi i i i inherente h recursiva i d de un problema bl no significa i ifi que sea ms eficiente que una solucin iterativa. Dos aspectos que influyen en la ineficiencia de algunas soluciones recursivas:

El tiempo asociado con la llamada a las rutinas es una cuestin a tener en cuenta:Merece la pena la facilidad de elaboracin del algoritmo con respecto al costo en tiempo de ejecucin que incrementar la gestin de la pila originado por el gran nmero de posibles llamadas recursivas? La ineficiencia inherente de algunos algoritmos recursivos. Por ejemplo, en la solucin l i fibonacci, fib i l la mayora d de los l clculos l l se repiten i varias i veces.

Solucin: Evitar procesamientos duplicado mediante la utilizacin de un vector o una lista, que mantuviera toda la informacin calculada hasta el momento. Otro problema: el tamao del problema a ser resuelto recursivamente. Si este implica una profundidad de recursin muy grande, olvidarla.

Recursividad o Iteracin
50

Problemas

de eficiencia

Recursividad o Iteracin
51

Problemas

de eficiencia

Recursividad o Iteracin
52

Problemas

de eficiencia

Recursividad o Iteracin
53

Problemas

de eficiencia

Recursividad o Iteracin
54

Problemas

de eficiencia

Recursividad o Iteracin
55

Problemas

de eficiencia

Recursividad o Iteracin
56

C d llevarla Cundo ll l a cabo b


Cuando La

los lenguajes no permiten la recursividad.

solucin recursiva sea muy costosa computacionalmente. que el esfuerzo de realizar la conversin compense la ganancia obtenida con la nueva implementacin recursiva

Siempre

57

Recursividad. Eliminacin

Recursividad. Eliminacin
58

1.

Eliminacin de la recursin de cola (tail recursion ).

Recursin de cola: cuando existe una llamada recursiva en un mdulo que es la ltima instruccin de una rutina. Eliminar la recursin de cola: Paso a estructura iterativa (mediante ciclo while):

If(condicin){ Ejecutar una tarea. Actualizar condiciones. Llamada recursiva. recursiva }

while hil (condicin){ ( di i ){ Ejecutar tarea. Actualizar condiciones. }

El mecanismo de eliminacin de la recursividad de la cola es tan mecnico que hay compiladores que lo hacen automticamente.

Recursividad. Eliminacin
59

Recursividad. Eliminacin
60

Ej Ejemplo l i impresin i en orden d inverso i d de un vector en J Java.


public void Imp_OrdenInversoVector( int Vector [], int Tamanio){ if (Tamanio >0) { System.out.println ( +Vector[Tamanio-1]); Imp_OrdenInversoVector(Vector, Tamanio-1); } }

Eliminando la recursin de cola en Java:


public void Imp p p_OrdenInversoVector ( (int Vector[], [], int Tamanio){ ){ while (Tamanio>0){ System.out.println ( + Vector[Tamanio-1]); -- Tamanio; } }

Recursividad. Eliminacin
61

Cmo eliminar el resto de casos recursivos


Cmo

acta el sistema para hacer posible la recursividad

???
Podemos

emular ese comportamiento en nuestro cdigo prescindiendo de las llamadas recursivas?

Recursividad. Eliminacin
62

Q ocurre cuando Qu d se utiliza ili l la recursividad i id d

Cada llamada recursiva conlleva:


La introduccin en la pila de los valores actuales de las variables locales Almacenamiento en la p pila de la direccin de retorno Asignacin de valores de entrada a los parmetros Se transfiere la ejecucin a la primera sentencia La extraccin de la pila de la direccin de retorno R Recuperacin i d de l los valores l d de las l variables i bl l locales l Ejecucin a partir de la sentencia siguiente antes de la llamada

La vuelta de cada llamada recursiva conlleva:


Recursividad. Eliminacin
63

Qu ocurre cuando se utiliza la recursividad


Eliminacin de la recursin mediante la utilizacin de pilas. Llamada a una rutina:


1. 2. 3. 4 4.

se introducen en la pila los valores de las variables locales, la direccin de la siguiente instruccin a ejecutar una vez que finalice la llamada, se asignan los parmetros actuales a los formales y se comienza la ejecucin por la primera instruccin de la rutina llamada. llamada se saca de la p pila la direccin de retorno

Finalizacin de la rutina:
1. 2.

y los valores de las variables locales, 3. se ejecuta la siguiente instruccin.

Recursividad. Eliminacin
64

En

esta tcnica de eliminacin de recursividad:

el programador implementa una estructura de datos con la que simular la pila del ordenador, introducir los valores de las variables locales y parmetros en la l pila, il en lugar l de d hacer h l las ll llamadas d recursivas, i los sacar para comprobar si se cumplen los casos bases. Se aade un bucle, generalmente while, que iterar mientras la pila no est vaca, hecho que significa que se han finalizado las llamadas recursivas. recursivas

Recursividad. Eliminacin
65

Tcnica T i general ld de eliminacin li i i de d recursividad i id d utilizando tili d pilas il Definir una pila que permita almacenar las variables locales y el valor de retorno en caso de existir Sustituir cada variable local por el campo que le corresponda de la parte superior de la pila Envolver el resto del cdigo en un bucle (tpicamente while) Por cada llamada recursiva:

Disponer en la pila los valores de las variables y resto de informacin Reiniciar el lb bucle l ( (continue) ) Recuperar la cima de la pila y usar el valor de retorno Preparar el valor de retorno que corresponda y disponerlo en la pila Saltar hasta el punto del bucle apropiado segn la direccin de retorno

Por cada vuelta atrs de la recursin (return): ( )


Recursividad. Eliminacin
66

Recursividad. Eliminacin
67

Recursividad. Eliminacin
68

public i int i ncsr_nr(int (i n, int i k){ ){ tPila Pila;int Suma=0;Pila=crear();push(n,Pila);push(k,Pila); while (!vacia(Pila)) { k= tope(Pila); k pop(Pila); n= tope(Pila); pop(Pila); if (k >n ) Suma += 0; 0 else if (k == n || k== 0) Suma +=1; ; else{ push(n-1, Pila); push(k-1, Pila); push(n-1, Pila); push(k, Pila); } } destruir(Pila); return Suma; ; }

Recursividad. Eliminacin
69

De

manera general, dada una estructura recursiva bsica de la forma:


RutinaRecursiva(parmetros){ Si se han alcanzado los casos bases entonces{ Acciones que correspondan a dichos casos bases. }Si no{ } { Llamada recursiva con los parmetros correspondientes. } }

Recursividad. Eliminacin
70

L estructura La t t bsica b i de d la l eliminacin li i i de d la l recursividad i id d es la l siguiente: i i t


RutinaNoRecursiva(parmetros){ Meter los parmetros y variables locales en la pila. Repetir mientras no est vaca la pila{ { Sacar los elementos que estn en el tope de la pila Si stos cumplen los casos bases Entonces{ Acciones que correspondan a dichos casos bases. }Si no{ Meter en la pila los valores con los que se producira la(s) llamada(s) recursiva(s). } } }

OJO! Tantas pilas como tipos de parmetros y variables locales.

71

Recursividad. Divide y Vencers

Recursividad. Divide y Vencers


72

Tcnica T i

de d guerra aplicada li d a la l resolucin l i de d problemas, convertida en paradigma de diseo de algoritmos. g de dividir el p problema a tratar en otros ms pequeos hasta que sea posible resolverlos para aprovechar el paralelismo de las mquinas actuales repartir el correo en una gran ciudad?

Trata

Ideal

Cmo

Recursividad. Divide y Vencers


73

Si

el tamao del problema es menor de un umbral dado entonces:


aplicar un algoritmo sencillo para resolverlo o encontrar e co a la a solucin so uc directa. d ec a.

si

no
dividir di idi el l problema bl d de en m subproblemas b bl y encontrar la l solucin a cada uno de ellos.

Combinar C bi

las l soluciones l i d de l los m problemas bl para obtener la solucin final.

Recursividad. Divide y Vencers


74

Problemas tpicos Algunos problemas tratables con esta tcnica algortmica:


Bsqueda q binaria (Babilonia, ( , 200AC) ) Multiplicacin de nmeros muy grandes Torres de Hanoi Ordenacin por mezcla (Merge-Sort)

Recursividad. Divide y Vencers


75

Ej Ejemplo l sencillo: ill

Recursividad. Divide y Vencers


76

Ejemplo: Ej l bsqueda b d binaria bi i de d un valor l en un vector t ordenado. Si el l elemento l t b buscado d est t en la l posicin i i que ocupa la mitad del vector, concluir la bsqueda. Si no es as as, determinar en qu mitad debera estar el elemento: si fuera menor que el valor de la mitad buscar en la mitad izquierda, y si fuera mayor, en la parte derecha. Cundo acabaramos? el valor buscado es encontrado, o cuando el tamao del vector sea cero, lo que indica que no est el valor buscado.

Recursividad. Divide y Vencers


77

Bsqueda binaria:

Recursividad. Divide y Vencers


78

public int BusqBinaria(int Vector [],int [] int LimInf,int LimInf int LimSup, LimSup int Valor){ int Mitad; if (LimInf > LimSup) return -1; 1; else{ Mitad= (LimInf + LimSup)/2; if ( (Valor == Vector[Mitad]) [ ]) return Mitad; else if (Valor <= Vector[Mitad]) return BusqBinaria(Vector, LimInf, Mitad-1, Valor); else return BusqBinaria(Vector, Mitad+1, LimSup,Valor); } }

Recursividad. Divide y Vencers


79

Ejemplo: Las torres de Hanoi.

Utilizando tres postes (A, B y C) y n discos de diferentes tamaos y con un agujero en sus mitades p para que q pudieran p meterse en los postes, p y considerando que q un disco slo puede p situarse en un poste encima de uno de tamao mayor, el problema consista en pasarlos, de uno en uno, del poste A, donde estaban inicialmente colocados, al poste B, utilizando como poste auxiliar el restante (C), cumpliendo siempre la restriccin de que un disco mayor no se pueda situar encima de otro menor. menor

Recursividad. Divide y Vencers


80

Ejemplo: Las torres de Hanoi.

Utilizando tres postes (A, B y C) y n discos de diferentes tamaos y con un agujero en sus mitades p para que q pudieran p meterse en los postes, p y considerando que q un disco slo puede p situarse en un poste encima de uno de tamao mayor, el problema consista en pasarlos, de uno en uno, del poste A, donde estaban inicialmente colocados, al poste B, utilizando como poste auxiliar el restante (C), cumpliendo siempre la restriccin de que un disco mayor no se pueda situar encima de otro menor. menor

Recursividad. Divide y Vencers


81

Solucin:
Para un disco: moverlo de A a B. Para ms de un disco:

Solventar el problema para n-1 discos, ignorando el ltimo de ellos, pero ahora teniendo en cuenta que el poste destino ser C y B ser el auxiliar Una vez hecho esto anterior, los n - 1 discos estarn en C y el ms grande permanecer en A. Por tanto, tendramos el problema cuando n = 1, en cuyo caso se movera ese disco de A a B P ltimo, Por l i nos queda d mover los l n-1 1 di discos de d CaB B, utilizando ili d A como poste auxiliar.

Recursividad. Divide y Vencers


82

S l i Solucin:
Si numeramos los discos desde 1 hasta n, y llamamos X a la primera pila de discos (origen), Z a la tercera (destino) e Y a la intermedia (auxiliar) y a la funcin le llamaramos hanoi (origen, auxiliar, destino), como parmetros, la funcin recibira las pilas de discos. El algoritmo de la funcin sera el siguiente:
1. Si

origen == {0}: mover el disco 1 de pila origen a la pila destino (insertarlo arriba de la pila destino); terminar. 2. Si no: hanoi({0...n-1},destino, auxiliar) //mover todas las fichas menos la ms grande (n) ( ) a la varilla auxiliar 3. mover disco n a destino //mover la ficha grande hasta la varilla final 4. hanoi (auxiliar, origen, destino) // //mover todas las fichas restantes, { {0...n1}, encima de la ficha grande (n) 5. terminar

Recursividad. Divide y Vencers


83

public bli void id TorresHanoi(int T H i(i t NumDiscos, N Di char h Origen, Oi char h Destino, D ti char Auxiliar){ if(NumDiscos ( == 1) ) Sytem.out.println("Mover el disco de arriba del poste+ Origen+al + Destino); else{ TorresHanoi(NumDiscos-1, Origen, Auxiliar,Destino); TorresHanoi(1 Origen TorresHanoi(1, Origen, Destino, Destino Auxiliar); TorresHanoi(NumDiscos-1, Auxiliar, Destino,Origen); } }

Recursividad. Divide y Vencers


84

/* {Pre: discos > 1 ^ discos = nmero de discos ^ ini,dest,aux ini dest aux = caracteres que identifiquen las torres} {Post: Se escribe por el canal estndar de salida los movimientos a realizar, indicados a partir de los caracteres que identifican las torres, para llevar todos los discos desde la torre inicial a la de destino} */ void hanoi(int discos, discos char ini, ini char dest, dest char aux) { if (discos == 1) cout << ini << " --> " << dest << endl; else { hanoi(discos ( - 1, , ini, , aux, , dest); ); cout << ini << " --> " << dest << endl; hanoi(discos - 1, aux, dest, ini); } } /* Ejemplo de funcin que llama automticamente a hanoi(int, char, char, char) solo dndole el nmero de discos {Pre: discos > 1} {Post: Se escribe por el canal estndar de salida los movimientos a realizar para llevar todos los discos desde la torre de inicio hasta la de destino. Las torres sern identificadas como M A V siendo la inicial M y la de destino V} */ void hanoi(int discos) { hanoi(discos, 'M', 'A', 'V'); }

Recursividad. Divide y Vencers


85

Ej Ejemplo l Hanoi(5) H i( )

1. 2. 3 3. 4. 5. 6 6. 7. 8.

M --> A M --> V A --> >V M --> A V --> M V --> >A M --> A M --> V

9. A --> V 10. A --> M 11 V --> 11. >M 12. A --> V 13. M --> A 14 M --> 14. >V 15. A --> V 16. M --> A

17. V --> M 18. V --> A 19 M --> 19. >A 20. V --> M 21. A --> V 22 A --> 22. >M 23. V --> M 24. V --> A

25. M --> A 26. M --> V 27 A --> 27. >V 28. M --> A 29. V --> M 30 V --> 30. >A 31. M --> A

Recursividad. Divide y Vencers


86

Mtodo

de biseccin Bsqueda de races

Recursividad. Divide y Vencers


87

Mtodo de biseccin Clculo raz cuadrada double sqrtBisect(double n, double min, double max) { if(abs(max-min)<=PRECISION) return min; else { double medio = (max+min)/2; if(medio*medio<n) return sqrtBisect(n,medio,max); q ( , , ); else return sqrtBisect(n,min,medio); } } Parmetros: n = Nmero del que se quiere calcular la raz cuadrada min = Lmite inferior del espacio de bsqueda max = Lmite superior del espacio de bsqueda

Recursividad. Divide y Vencers


88

Mtodo de biseccin Clculo raz cuadrada

89

Recursividad. Backtracking

Recursividad. Backtracking
90

Tcnica

de construccin incremental de soluciones a un problema. solucin puede ser nica o no (soluciones alternativas). l i ) una bsqueda b d sistemtica i i por todas d las l posibles configuraciones del espacio de bsqueda. no ha hecho un sudoku alguna vez?

La

Realiza R li

Quin

Recursividad. Backtracking
91

Problemas tpicos Algunos problemas tratables con esta tcnica algortmica:


Clsicos: 8 reinas, ,7p puzzle, , salto del caballo Problemas combinatorios: variaciones, permutaciones, coloreado de mapas p TSP (Traveling Salesperson Problem) Problemas de optimizacin p en general g

Recursividad. Backtracking
92

Algoritmo Al i general l Basado en el algoritmo de bsqueda en profundidad recursiva:


Cada nodo representa un estado que puede representar una solucin l i ( (configuracin fi i vlida) lid ) o no Las aristas salientes representan acciones, decisiones que alteran el estado de la solucin que est construyndose Si una arista lleva a una configuracin no vlida se vuelve atrs hacia el nodo padre p Si una arista lleva a una solucin se guarda/comunica y el proceso puede detenerse o continuar segn necesidad

Recursividad. Backtracking
93

Recursividad. Backtracking
94

Problema de las n reinas

Recursividad. Backtracking
95

Ejemplo: Ej l el l problema bl d de l las ocho h reinas i Un tablero de ajedrez, el cual tiene un total de 64 casillas (8 filas x 8 columnas). co u as) El problema p ob e a consiste co s s e en e situar s ua ocho oc o reinas e as en e el e tablero ab e o de tal forma que no se den jaque entre ellas. Una reina puede dar jaque a aquellas reinas que se siten en la misma fila, columna o diagonal en la que se encuentra dicha reina. reina Solucin:

Meter la primera reina. Meter la segunda en una casilla que no est atacada por la primera reina. Meter la tercera en una casilla no atacada por la primera o la segunda. Meter sucesivamente el resto de reinas reinas. Si en algn momento no puede colocarse una reina, ir deshaciendo movimientos de las reinas ya colocadas y a partir de esa reorganizacin continuar la colocacin del resto de reinas.

Recursividad. Backtracking
96

Funciones auxiliares: void AsignarReinaA(int Fila, int Columa) => Sita un 1 en la casilla ill (Fila, (Fil Columna) C l )i indicando di d que est ocupada d por una reina. void id EliminarReinaDe(int Eli i R i D (i t Fila, Fil int i t Columna) C l ) => > Sita Sit un 0 en l la casilla (Fila, Columna) indicando que esa casilla est libre (antes estaba ocupada por una reina y ahora deja de estarlo). int RecibeJaqueEn(int q ( Fila, , int Columna) ) => Devuelve 1 si la casilla (Fila, Columna) recibe jaque de alguna reina y 0 en caso contrario.

Recursividad. Backtracking
97

public bli void id SituarReina(int Sit R i (i t Columna) C l ){ /* Columna indica en qu columna se quiere situar la reina, y Situada es una variable que tomar el valor 1 cuando se haya logrado ubicar correctamente a la reina correspondiente, y 0 cuando el intento haya sido infructuoso. */ int Fila, Situada; if (Columna > 7){ Situada=1; return Situada; else { Situada=0; Fila=1; while (!(Situada) && (Fila <= 7)) if (RecibeJaqueEn(Fila, Columna)) ++Fila; else { AsignarReinaA(Fila, Columna); Sit d Sit R i (C l Situada=SituarReina(Columna+1); +1) if ( !(Situada)) { EliminaReinaDe(Fila, Columna); ++Fila; } } } return Situada; }

98

Captulo 2. Recursividad Bibliografa


[AU87] A.V. A V Aho, Aho J.A. J A Ullman. Ullman Data structures and algorithms. algorithms AddisonAddison Wesley.1992. Wesley 1992 [FGG98] J. Fernndez, A. Garrido, M. Garca. Estructuras de datos. Un enfoque prctico usando C. Universidad de Granada, 1998. [JZ04] Luis L i Joyanes J A il I Aguilar, Ignacio i Zahonero Z h M i Martinez. Al i Algoritmos y estructuras d de datos. d Una U perspectiva en C. MCGRAW-HILL / INTERAMERICANA DE ESPAA, S.A., 2004 [Pres01] R.S. Pressman. Ingeniera del software, Un enfoque prctico. Mc Graw Hill. 2001. Bibliografa en la web: The animation of recursin

http://www.animatedrecursion.com/simple http://www.cosc.canterbury.ac.nz/mukundan/dsal/ToHdb.html http://www.hbmeyer.de/backtrack/backtren.htm http://www.ritmodominicano.com/wiki.php?title=Vuelta_atr%C3%A1s

Applet animacin Torres de Hanoi

Animacin puzzle backtraking

Vuelta atrs (apuntes sobre backtraking)

You might also like