AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Tema 2: Análisis y Diseño de Algoritmos Recursivos. Objetivos. Introducir las bases necesarias para el diseño y análisis de los algoritmos recursivos. Bibliografía. BÁSICA: Brassard, P. Bratley: “Algorítmica: concepción y análisis”. Masson, 1990. AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Contenidos. 1. INTRODUCCIÓN : ALGORITMOS RECURSIVOS 2. INDUCCIÓN 2.1 PRINCIPIO DE INDUCCIÓN 2.2 VERIFICACIÓN DE ALGORITMOS RECURSIVOS 3. ETAPAS DEL DISEÑO RECURSIVO. 4. ANÁLISIS DE LA COMPLEJIDAD TEMPORAL DE LOS ALGORITMOS RECURSIVOS Scholl P.C. Algorítmica y Representación de Datos. Tomo 2: Recursividad y Arboles. Ed. Masson, 1986. Casanova A. Programación. Servicio de Publicaciones UPV, València, 1993. OTROS: Aho A.V., Hopcroft J.E., Ullman J.U. The Design and Analysis of Computer Algorithms. Ed.Addison-Wesley, 1974 Balcázar J.L. “Programación Metódica”. McGraw-Hill, 1993 Grimaldi R.P. Matemáticas Discreta y Combinatoria. Ed. Addison Wesley Iberoamericana, 1984 Sahni S. Concepts in Discrete Mathematics. The Camelot Publishing Company, 1985 1 2 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos 1. INTRODUCCIÓN : Algoritmos recursivos AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Un algoritmo A que resuelve un problema P es recursivo si está basado directa o indirectamente en sí mismo. - Un objeto es recursivo si su definición requiere la definición previa del objeto en un caso más sencillo. Ejemplo: Números Naturales N Problema P con Datos I (a) el 0 es un número natural. resuelto (b) el sucesor de un número natural es también un número natural. en términos de ... Problema P con Datos I' I - Una función es recursiva si su resolución requiere la solución previa de la función para casos más sencillos. con: Ejemplo: I, I' del mismo tipo I'I (a) 0!=1 Cuando I' es lo más pequeña posible, solución directa (b) n!=n (n-1)! 3 4 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos ESQUEMA DE SENCILLO : UN ALGORITMO RECURSIVO h( x ) d ( x) f ( x) c( x , f (ant ( x )) d ( x ) {P(x)} función f(x:T1) devuelve T2 opción d(x): r:=h(x); /*Casos directos*/ d(x): v:=f(ant(x)); r:=c(x,v); /*Casos recursivos*/ AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos TIPOS DE RECURSIÓN 1.- RECURSIÓN LINEAL : Si cada llamada recursiva genera, como mucho otra llamada recursiva - FINAL : si la llamada recursiva es la última operación que se efectúa, devolviéndose como resultado lo que se haya obtenido de la llamada recursiva sin modificación alguna. - NO FINAL : El resultado obtenido de la llamada recursiva se combina para dar lugar al resultado de la función que realiza la llamada. fopción devuelve r 2.- RECURSIÓN MÚLTIPLE : si alguna llamada puede generar más de una llamada adicional. ffunción {Q(x,r)} Cada llamada recursiva (activación de la función) posee su propio conjunto de variables locales y parámetros. Existen tantos objetos con un mismo nombre como activaciones de la función estén pendientes de terminar. La comunicación entre las sucesivas activaciones debe hacerse por medio de parámetros. 5 6 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos EJEMPLOS : RECURSIÓN LINEAL FINAL Supongamos que hacemos la llamada MCD(25,15) Traza : Secuencia de llamadas : {n 0 m 0} función MCD(n,m:entero)devuelve entero MCD(25,15) var r :entero ; MCD(25,15) n,m opción r = MCD(n-m,m) 10,15 n=m : r :=n ; n>m : r :=MCD(n-m,m) ; MCD(n-m,m) n<m : r :=MCD(n,m-n) ; 10,15 fopción n,m r = MCD(n,m-n) 10,5 n,m devuelve r ffunción n,m r=MCD(n-m,m) MCD(n,m-n) {MCD(n,m) es el m·ximo entero que divide a n y a m} 10,5 5,5 n,m n,m {r=5} {r=5} MCD(n-m,m) {r=5} 5,5 {r=5} n,m 7 8 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos RECURSIÓN LINEAL NO FINAL : AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Supongamos que la llamada inicial es FACT(4) Secuencia de llamadas : {n 0} función FACT (n:entero)devuelve entero var r,v :entero ; opción n=0 : r :=1 ; n>0 : v := FACT(n-1) ; r :=v*n; fopción devuelve r ffunción {FACT(n)=n†!} 9 FACT(4) n FACT(n-1) 3 n FACT(n-1) 2 n FACT(n-1) 1 n FACT(n-1) 0 n Llamada inicial Caso Directo 10 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Traza : AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos RECURSIÓN MÚLTIPLE : FACT(4) n=4 v :=FACT(n-1) ; n=3 v :=FACT(n-1) ; n=2 v :=FACT(n-1) ; n=1 v :=FACT(n-1) ; n=0 r :=1 ; {v=1} r :=v*n {r=1*1=1} {v=1} r :=v*n {r=1*2=2} {v=2} r :=v*n {r=2*3=6} {v=6} r :=v*n {r=6*4=24} 11 {n 0} función Fib(n:entero)devuelve entero ; var r :entero ; opción n1 : r:=n ; n>1 : r:=Fib(n-1)+Fib(n-2) ; fopción devuelve r ffunción {Fib(n)=Fibonacci(n)} donde n n 1 Fibonacci (n) Fibonacci ( n 1 ) Fibonacci ( n 2 ) n 1 12 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Traza : Supongamos que la llamada es Fib(4) : Árbol de llamadas : Fib(4) Fib(3) Fib(2) Fib(1) Fib(2) Fib(1) Fib(0) 13 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Fib(1) Fib(0) Fib(4) Llamada inicial n Fib(n-1) n=3 Fib(n-1) n=2 Fib(n-1) n=1 {r=1} Fib(n-2) n=0 {r=0} {r=1+0=1} Fib(n-2) n=1 {r=1} {r=1+1=2} Fib(n-2) n=2 Fib(n-1) n=1 {r=1} Fib(n-2) n=0 {r=0} {r=1+0=1} {r=2+1=3} 14 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos 2. INDUCCIÓN Si queremos demostrar la correcciÛn de un algoritmo Para comprobar que un algoritmo recursivo es correcto hay que analizar los aspectos siguientes : recursivo .... øQU… M…TODO DE DEMOSTRACI”N 1.- ¿Hay una salida no recursiva del algoritmo (Caso Directo) ?, ¿El algoritmo cumple con la especificación en este caso ? PODEMOS USAR? 1. Debemos analizar todas y cada una de las instrucciones del algoritmo. 2.- ¿Cada llamada recursiva se refiere a un caso más pequeño del problema original ? 2. Pero .... !!! incluye instrucciones que consisten en ejecutar el mismo algoritmo ("llamadas recursivas") !! Idea : Suponer que estas llamadas funcionan correctamente e intentar demostrar que la función que hace la llamada también. 3.- Suponiendo que la(s) llamada(s) recursivas cumplen la especificación (son correctas), ¿cumple la especificación el algoritmo completo ? Aplicar el método de demostración por inducción 15 16 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Principio de Inducción Fuerte 2.1 PRINCIPIO DE INDUCCIÓN. Principio de Inducción Fuerte FASE 1: BASE INDUCCIÓN FASE 1: BASE INDUCCIÓN Probar que la propiedad P es cierta para n0 0, n0 N. (Para ello se utilizan las propiedades de los naturales.) Probar que la propiedad P es cierta para n0 0, n0 N. (Para ello se utilizan las propiedades de los naturales.) FASE 2: INDUCCIÓN FASE 2: INDUCCIÓN 2a) HIPÓTESIS DE INDUCCIÓN: Supongo que P es cierta x [n0, n], n n0, n0, n, x N. Probar que P es hereditara 2a) HIPÓTESIS DE INDUCCIÓN: Supongo P cierta para n N / n n0 2b) PRUEBA: Probar que P es cierta para n+1. (Para ello se utilizan las propiedades de los N y la hipótesis de inducción.) 2b) PRUEBA: Probar que P es cierta para n+1. (Para ello se utilizan las propiedades de los N y la hipótesis de inducción.) FASE 3: CONCLUSIÓN Si hemos concluido con éxito las dos fases anteriores P es cierta n N, n n0, n0 N FASE 3: CONCLUSIÓN Si hemos concluido con éxito las dos fases anteriores P es cierta n N, n n0, n0 N ( P(n0) n: ( P(n) P(n + 1) ) n: P(n)) ( n: ((x: x <n: P(x)) P(n))) n: P(n)) n0 x n0 n n+1 Probar que P es hereditara n n0 n0 17 18 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos PRUEBA POR INDUCCIÓN DE PROPIEDADES DE FUNCIONES RECURSIVAS. Ejemplo: Todo número de la forma 10 n -1 es divisible por 9. Sea f: D R una función recursiva. Sea P una propiedad de la función, tal como BASE DE INDUCCIÓN: CORRECCIÓN, TERMINACIÓN, OTRAS Probar que 100 - 1 es divisible por 9: 100 - 1 = 0 = 0 * 9 INDUCCIÓN: Ejemplo: Dada la función factorial 1 n 0 FACT (n) n * FACT (n 1) n 0 2a) HIPÓTESIS DE INDUCCIÓN: (a) Demostrar que termina. Supongo que 10n - 1 es divisible por 9 ( 10n - 1 = 9 * a) Como el dominio de FACT es N, utilizaremos el principio de inducción sobre N para la demostración 2b) PRUEBA: 10n+1 - 1 = 10 * (10n - 1) + 9 = 9 * (10 * a + 1) BASE: FACT(0) origina un número finito de cálculos INDUCCIÓN: HIPOTESIS: FACT(n - 1) origina un número finito de cálculos PRUEBA: ¿FACT(n) origina un número finito? Por definición , FACT(n) = FACT(n - 1) * n Por HI, FACT(n - 1) termina Entonces, FACT(n) también termina. 19 20 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos (b) Demostrar que es correcta, o sea que : FACT (n) n! donde n ! se define como n1 n 0 n ! i n 0 1 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos 2.2 VERIFICACIÓN DE ALGORITMOS RECURSIVOS. FUNCIÓN LIMITADORA. Consideremos el siguiente esquema : {P(x)} función f(x:T1) devuelve T2 BASE: FACT(0)=1 opción INDUCCIÓN: HIPÓTESIS: d(x): r:=h(x); /*Casos directos*/ FACT(n-1) = 1 * 2 *.. * (n - 1) n > 0 d(x): v:=f(ant(x)); r:=c(x,v); /*Casos recursivos*/ PRUEBA: ¿ FACT(n) = 1 * 2 * 3 * .. * n? fopción devuelve r Por definición , FACT(n)=n * FACT(n - 1) Por HI, FACT(n-1) = 1 * 2 * .. * (n - 1) ffunción {Q(x,r)} Entonces, FACT(n) = n * (1 * 2 * .. *(n - 1))=1 * 2 * .. * (n - 1) * n 21 22 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Para verificar este esquema consideraremos : CASOS DIRECTOS : Tendremos que demostrar {P(x)d(x)} r :=h(x) {Q(x,r)} La función limitadora : - Valida el razonamiento por inducción que equivale a demostrar P(x)d(x) {Q(x,h(x))} CASOS RECURSIVOS : 1.- Garantizar que los parámetros de la llamada recursiva cumplen la precondición : P(x) d(x) P(ant(x)) - Garantiza la terminación de la secuencia de llamadas recursivas, ya que cada una tiene que tener un valor natural t(x) estrictamente inferior al de la anterior y en los Naturales esto no puede ocurrir indefinidamente - De hecho es una cota superior del número de llamadas que se realizan a la función (cuando la recursión es lineal). 2.- Demostración por inducción de la corrección : P(x) d(x) Q(ant(x),v) Q(x,c(v,x)) H.I La verificación no es un argumento a posteriori sino que guia el diseño y explica el algoritmo. 3.- Validación del razonamiento inductivo : Definir una función limitadora t : T1 Natural Demostrar que t(x) decrece estrictamente en cada llamada : P(x) d(x) t(ant(x)) < t(x) 23 24 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos 3. ETAPAS DEL DISEÑO RECURSIVO. Un diseño recursivo constará de las siguientes etapas: AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos DEFINICIÓN DEL PROBLEMA Nombre del algoritmo, sus datos y sus resultados Precondición Postcondición 1.- Definición del problema. 2.- Análisis de casos. Identificación de la función limitadora. 3.-Transcripción algorítmica y verificación de cada caso. 4.-Validación de la inducción : la función limitadora decrece estrictamente en las llamadas. ANÁLISIS POR CASOS. IDENTIFICACIÓN DE LA FUNCIÓN LIMITADORA. Analizar los diferentes casos que se puedan presentar, identificando : Uno (o más) CASOS DIRECTOS Uno (o mas) CASOS RECURSIVOS Concretar la FUNCIÓN LIMITADORA OBSERVACIONES : 1.- Es preciso asegurarse de que se cubren todos los casos que pueden aparecer. 2.- Frecuentemente, la elección de los casos directos puede realizarse antes de decidir la función limitadora, basta comparar P y Q para ver en qué casos es fácil obtener Q a partir de P. Así los casos directos pueden ayudar a buscar la función limitadora : decrementar ésta debe suponer aproximarse al caso directo. 25 26 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos DISEÑO Y VERIFICACIÓN DE CADA CASO Diseño del fragmento de programa que resuelve cada caso junto con su verificación : (1) Al programar los casos recursivos es preciso suponer, como Hipótesis de Inducción, que las llamadas recursivas funcionan correctamente. (2) Para poder aplicar la inducción ha de garantizarse que, al evaluar la función limitadora sobre los parámetros que aparecen en cada llamada, se obtienen valores estrictamente menores que los que corresponden a los recibidos. Como subproducto de (2) queda demostrado que la recursión es finita, ya que no puede haber infinitas llamadas recursivas tales que cada una de ellas tenga asociado un número natural estrictamente inferior al de la anterior. AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos PROBLEMA 1: MULTIPLICACIÓN DE NATURALES Supongamos que el repertorio de instrucciones disponibles sobre los naturales se reduce a la suma y la diferencia. Queremos diseñar un algoritmo recursivo para realizar la multiplicación de naturales. Definición : algoritmo MULT (Datos a,b :entero Resultado p :entero) Precondición {a 0 b 0} Postcondición {p=a*b} Análisis de casos. Función limitadora. Hemos de distinguir al menos un caso directo y otro recursivo, éste nos ha de permitir hacer decrecer los parámetros en algún sentido. Tomemos como función limitadora “a” e intentemos decrementarla de 1 en 1 : Caso DIRECTO : a=0 Casos RECURSIVOS : a>0 27 28 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Solución al Caso Directo : AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos El algoritmo queda : {a 0 b 0} {a=0} función MULT(a,b:entero)devuelve entero; ?? p :=0 var p :Natural opción {p=a*b} a=0 : p :=0 ; Solución a los Casos recursivos : a>0 : p :=MULT(a-1,b) ; {p=(a-1)*b} Obsérvese que a*b=(a-1+1)*b=(a-1)*b+b p :=p+b ; fopción {a>0} {p=a*b} devuelve p p :=MULT(a-1,b) ffunción {p=(a-1)*b)} H.I ?? {MULT(a,b)=a*b} p :=p+b ¿Cuántas llamadas recursivas hace MULT(a,b) ? a {p=a*b} PRIMERA MEJORA : Hacer decrecer el menor de a y b 29 30 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Diseño de ? ? SEGUNDA MEJORA : Si a es PAR : 2*(a div 2)*b=a*b Suponiendo que además de las operaciones + y - se pueden usar ciertas multiplicaciones y divisiones (por 2). Si a es impar : (a div 2)=(a-1) div 2 Intentemos decrementar a de otra manera : dividiendo por 2 2*(a div 2)*b=2*((a-1) div 2)*b=(a-1)*b luego a*b=2*(a div 2)*b+b=MULT2(a div 2,b)+b Hemos de garantizar que a div 2 < a (en el caso recursivo): Algoritmo resultante : Caso DIRECTO : a=0 {a 0 b 0} Casos RECURSIVOS : a>0 función MULT2(a,b:entero)devuelve entero; Solución al Caso directo : igual que antes var p :entero opción Solución a los Casos recursivos : a=0 : p :=0 ; a>0 : p :=MULT(adiv2,b); {a>0} {p=(a div 2)*b} p :=MULT2(a div 2,b) opción {p=(a div 2)*b)} H.I par(a): p:=p*2; ?? par(a): p:=p*2+b fopción {p=a*b} {p=a*b} devuelve p ffunción {MULT2(a,b)=a*b} ¿Cuántas llamadas recursivas se realizan en este caso ? log a 31 32 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos PROBLEMA 2: Cálculo del cociente y el resto de la división entera. Dados dos enteros a 0 y b > 0 se desea obtener q, r tales que a = b * q + r q 0, 0 r < b Solo usaremos +, - y multiplicaciones y divisiones por 2. DEFINICIÓN: algoritmo DIVIDIR (Datos a,b :entero Resultados q,r :entero) AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos ANALISIS POR CASOS Y FUNCIÓN LIMITADORA : Observemos que : a - b = b * (q - 1) + r, 0 r < b q - 1 0 donde “q-1” es el cociente de “(a-b) div b” y “r” es el resto Esto nos da una pista para tomar como función limitadora a y reducir su valor en la forma a-b. Esto requiere como guarda que a b, quedando a<b como caso directo : Casos directos : a<b Casos recursivos : a b Precondición {a 0 b>0} Postcondición {a=b*q+r 0r<b q 0} Solución de los Casos Directos : {b>0 a<b} ?? q :=0 ; r :=a ; {a=b*q+r r<b q 0} Solución de los Casos Recursivos : {b>0 a b} DIVIDIR(a-b,b,q,r) ; {a-b=b*q+r} {a=b*(q+1)+r} q :=q+1 ; {a=b*q+r r<b q 0} 33 34 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos ALGORITMO RESULTANTE : AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Ejercicios propuestos : (1) ¿Podríamos basar el diseño en reducir a en 1 ? {a 0 b>0} acción dividir(ent a,b:entero; sal q,r :entero) opción a<b: q :=0;r :=a ; a b: dividir(a-b,b,q,r); (2) Diseñar un algoritmo reduciendo el parámetro “a” mediante una división por 2. (3) Diseñar un algoritmo incrementando el parámetro “b” duplicándolo. q :=q+1 ; fopción ffunción {a=b*q+rq 00r<b q 0} 35 36 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos PROBLEMA 3 : SUMAR LAS “i” COMPONENTES DE UN VECTOR “v”. AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos PRIMERAS ANÁLISIS DE CASOS Y FUNCIÓN LIMITADORA : CASO DIRECTO : i=0, anula el dominio del cuantificador de Q. La solución es s :=0 Supongamos definido : tipo TipoVector=vector [1..N] de entero ; CASOS RECURSIVOS : i>0 DEFINICIÓN : Como función limitadora elegiremos el valor de “i” algoritmo SUMAV (Datos v :TipoVector ;i :entero Resultado s : entero) {iN i>0} s :=SUMAV(a,i-1) ; Precondición : {0iN} Postcondición : {SUMAV(v)=j=1..i v[j] } {s=j=1..i-1 v[j] } ?? {s=j=1..i v[j] } 37 38 s :=s+a[i] AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos 4. ANÁLISIS DE LA COMPLEJIDAD TEMPORAL DE LOS ALGORITMOS RECURSIVOS. Algoritmo resultante : función SumaV(v:TipoVector;i:entero) devuelve entero var s :entero ; opción i=0 : s :=0 ; i>0 : s :=SumaV(v,i-1) ; s :=s+v[i] ; fopción devuelve s ffunción Si la definición recursiva es: h( x ) si d ( x ) f (x ) c( x, f (ant1( x )),..., f (ant m ( x ))) si d ( x ) el coste del algoritmo asociado vendrá frecuentemente dado por: coste(n) = m coste( F(n) ) + g(n) si n > n0 coste (n) = no importa si n n0 donde: F es la función de reducción de la talla (n) en cada llamada recursiva. Normalmente F(n)<n, y más concretamente: F(n) = n–c ó F(n) = n/c. m es el número de llamadas recursivas que genera cada llamada a f(x), suponiendo que en todas ellas la talla se reduzca de la misma forma. g(n) es el coste de f(x) excluidas las llamadas recursivas. 39 40 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Resolveremos las relaciones de recurrencia por el método de sustitución. AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos EJEMPLO (Aplicación del método de sustitución). función máximo(a: vector; i: entero) devuelve entero; opción i=1: devuelve a[1]; i>1: devuelve mayor(máximo(a,i-1),a[i])); fopción ffunción La primera llamada es máximo(a,n), siendo n el nº de elementos del vector. • La talla del problema es n. • No hay diferentes instancias; en cualquier caso se recorre todo el vector. Las relaciones de recurrencia serán: coste( 1 ) = K1 coste( n ) = coste( n-1 ) + K2 41 42 n>1. AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos El método de sustitución consiste en ir desarrollando la función, tomando valores decrecientes de n y sustituyendo en coste(n) hasta llegar al caso en que cesa la recurrencia (caso directo). AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Para obtener el orden de las relaciones más habituales, se puede aplicar el siguiente teorema. TEOREMA. Sean a 1, b R+, n, c N. Supóngase que f verifica para n c las relaciones indicadas. Entonces: En el ejemplo anterior: Caso 1 f(n) = a f(n-c) + b coste(1) = K1 coste(n) = coste(n-1) + K2 luego n>1, a=1 (n) a>1 (an/c) a=1 (n2) a>1 (an/c) a=1 (logcn) a>1 (nlogca) a<c (n) a=c (n logcn) a>c (nlogca) Caso 2 f(n) = a f(n-c) + bn + d coste(n) = coste(n-1) + k = coste(n-2) + 2k = coste(n-3) + 3k Caso 3 f(n) = a f(n/c) + b = coste(n-4) + 4k = .... = coste(n-(n-1)) + (n-1)k Caso 4 = coste(1) + (n-1)k f(n) = a f(n/c) + bn + d = k' + (n-1)k (n). 43 44 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Ejemplo: Las torres de Hanoi, en el que se deben mover n discos de uno en uno desde una pila inicial a otra destino haciendo uso de una tercera pila auxiliar, con la restricción de que cualquier disco, en cualquier momento, sólo puede tener por debajo de él discos de mayor diámetro. Procedimiento hanoi(n: natural; ini, dest, aux: pila de discos) es si n>0 entonces hanoi(n-1,ini,aux,dest); mueve_disco_sup(ini,dest); hanoi(n-1,aux,dest,ini) fsi fprocedimiento, donde mueve_disco_sup(a,b tiene coste (1). AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Al resolver por sustitución: coste(n) = 2 coste(n-1) + K1 n>0 coste(n) = K2 n=0 coste(n) = 2coste(n-1) + K1 = 2(2coste(n-2) + K1) + K1 = 4coste(n-2) +2 K1 + K1 = 4(2coste(n-3) + K1) + 2 K1+ K1 = 8coste(n-3) + 4 K1 + 2 K1 + K1 =...... n n-1 = 2 coste(0) +2 Talla del problema: n. No hay instancias diferentes. n n-2 K1 + 2 n n = 2 K2 + K1(2 -1) (2 ). Relaciones de recurrencia de la función de coste: coste(n) = 2 coste(n-1) + K1 n>0 n=0 coste(n) = K2 45 46 K1 + ... + 2 K1 + K1 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos EJEMPLO: Búsqueda dicotómica. (Aplicación de las relaciones de recurrencia a algoritmos iterativos.) { v está ordenado } procedimiento dicotómica (v: vector1..n de entero; n, x: entero; sal está: lógico; sal m: entero) es var i,j: entero fvar; i:=1 ; j:=n; está := falso; repetir m := (i+j) div 2; opción v[m] > x: j := m - 1; v[m] < x: i := m + 1; v[m] = x: está := verdadero; fopción hasta que i>j está fprocedimiento {1mn((está vm=x) (está k:1kn:vkx)} AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos (Caso peor) costep(n) = K1 + costep(n/2)) costep(1) = K2 Si se resuelve la recurrencia por sustitución: costep(n) = K1 + costep(n/2) 2 = K1 + K1 + costep(n/2 ) 2 = 2 K1 + costep(n/2 ) 3 = 2 K1 + K1 + costep(n/2 ) 4 La talla del problema es n = j-i+1 j-i = 3 K1 + K1 + costep(n/2 ) = .... Caso peor (x no está en v): como tras cada iteración la talla del problema disminuye aproximadamente a la mitad, se tiene que: = (log2n) K1 + costep(n/2 coste(n) = K1 + coste(n/2) 47 n>1 n>1 log n )) = (log2n) K1 + costep(n/n) = (log2n) K1 + K2 ( logn ). 48 AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos AD2 98/99. Tema 2: Análisis y Diseño de Algoritmos Recursivos Caso mejor: x se encuentra en la primera iteración. Resumen: coste(n) ( logn ) coste(n) !( 1 ) 49 50