EJERCICIOS DE ALGORÍTMICA Y COMPLEJIDAD DIVIDE Y VENCERÁS Ejercicio 1. La función mostrada implementa un algoritmo que busca un número dentro de un array de números naturales y devuelve el índice del elemento que lo contiene. Los índices del array son mayores que 0, por lo que en caso de que el número no se encuentre, éste será el valor a devolver. Además, el número de elementos del array siempre es potencia de 2. function Buscar (A : vector; prim, ult, buscado : natural) return natural is primero, ultimo, medio : natural; encontrado : boolean; begin primero := prim; ------ 1 ultimo := ult; ------ 1 encontrado := false; ------ 1 while primero <= ultimo and not encontrado loop ------ 3 medio := (primero + ultimo) / 2; ------ 4 if buscado = A(medio) then ------ 2 encontrado := true; ------ 1 elsif buscado < A(medio) then ------ 2 ultimo := medio - 1; ------ 2 else primero := medio + 1; ------ 2 end if; end loop; if encontrado then ------ 1 return medio; ------ 1 else return 0; ------ 1 end if; end Buscar; 1) ¿Cuál es la complejidad del algoritmo en función del número de elementos del array? 2) Calcular el tiempo de ejecución T(n) en estas situaciones: a) Para el mejor caso. b) Para el peor caso. 3) Proponer una versión del algoritmo acorde con la técnica de divide y vencerás. 4) ¿Cuál es la complejidad del nuevo algoritmo? 5) Asignar una duración razonable a cada sentencia del nuevo algoritmo y calcular los nuevos tiempos de ejecución T(n). a) Cuando el array consta de un único elemento. b) Para el mejor caso cuando el array contiene más de un elemento. c) Para el peor caso. Ejercicio 2. La siguiente función devuelve la suma de los dígitos que componen el número positivo que se le pasa como parámetro. function SumaDigitos (n: natural) return natural is suma, numero : natural; begin numero := n; ------ 1 suma := numero mod 10; ------ 3 while numero >= 10 loop ------ 1 numero := numero / 10; ------ 3 suma := suma + (numero mod 10); ------ 4 end loop; return suma; ------ 1 end SumaDigitos; 1) Calcular la complejidad del algoritmo. 2) Analizar la problemática que entrañaría el cálculo del tiempo de ejecución en función del número. 3) Modificar el algoritmo para que utilice divide y vencerás. 4) ¿Cuál será la complejidad ahora? 5) ¿Qué condición debería cumplir el número para que se pudiera aplicar la técnica del cambio de variable? 6) Para finalizar, una curiosidad. ¿Cómo sería la función más sencilla que devolviera la suma de los dígitos suponiendo que se da la condición del apartado anterior? Ejercicio 3. Dados dos números naturales x y n, se desea desarrollar un algoritmo que resuelva la expresión xn mediante multiplicaciones sucesivas de la base. 1) Escribir el algoritmo mediante la técnica divide y vencerás. 2) Calcular su complejidad en función del valor de n. 3) Si n siempre fuera una potencia de 2, ¿cómo se podría modificar el algoritmo para que fuera más eficiente? 4) Calcular, en función de n, el tiempo de ejecución del algoritmo modificado asimilando dicho tiempo con el número de veces que se le invoca. Ejercicio 4. A continuación se muestran dos funciones que calculan la media de los números contenidos en una matriz de dimensión N, que siempre será potencia de 2. M : array (1..N) of float; function media_1 (inicio, fin : natural) return float is begin if inicio = fin then return M(inicio); else return ( media_1 ( inicio, (inicio+fin)/2 ) + media_1 ( 1+(inicio+fin)/2, fin) ) / 2.0; end if; end media_1; function media_2 (inicio, fin : natural) return float is long : natural := fin - inicio + 1; suma : float := 0.0; begin if long < 8 then for i in inicio..fin loop suma := suma + M(i); end loop; return suma / float(long); else return ( media_2 ( V1, V2 ) + media_2 ( V3, V4 ) + media_2 ( V5, V6 ) + media_2 ( V7, V8 ) ) / 4.0; end if; end media_2; Ambas funciones tienen dos parámetros que indican los límites de la matriz. Lógicamente, las primeras llamadas tendrán la forma: media_1 ( 1, N ) y media_2 ( 1, N ) 1) Utilizar las ecuaciones de recurrencia para hallar una expresión que permita calcular el número de llamadas a la función "media_1" en virtud del valor de N. 2) ¿Qué valores deben tener las expresiones V1 a V8? 3) ¿Cuantas llamadas se harán a "media_2" para los siguientes valores de N? a) N = 1 b) N = 8 c) N = 32 4) Utilizar el teorema maestro para calcular la complejidad de ambos algoritmos.