UNIVERSIDAD TÉCNICA FEDERICO SANTA MARÍA DEPARTAMENTO DE INFORMÁTICA EX UMBRA IN SOLEM Estructura de Datos: Primer Certamen Primer Semestre, 2009 1.- (5 ptos) El algoritmo UNO demora 5n2 segundos en resolver un determinado problema con n datos de entrada, mientras que el algoritmo DOS demora n2+400n. ¿Cuál de los dos algortimos es mas eficiente en función de los datos de entrada? RESP.: 5n2 >= n2+400n 4n2 >= 400n (n2/n) >= (400/4) luego n >= 100 para n<=100 es el Algoritmo UNO para n>100 es el Algoritmo DOS 2.- (10 ptos.) Ordenar las siguientes funciones por orden de crecimiento: a) n b) SQRT(n) c) log n d) log (log n) g) SQRT(n)* log2n h) (1/3)n e) log2n f) n/log n RESP.: h<j<d<c<e<b<g<f<a<i 3.- (15 ptos.) Calcular la complejidad de los siguientes programas. a) { O(1) Error = a+n-1>B; if (!Error) { for (i=1;i <= n ; i++) c++; for (i=1; i <= n; i++) d++; O(n) O(n) } } b) reset(arch); mientras NO es fin de archivo(arch) haga { read (arch, ele); Para i:=1 hasta m haga elem[i]:=6; O(1) O(1) O(m) } O(m*n) c) { i++; while i<=n { m.indice =1; j=i+1; while j<=n { if datos[s]<datos[m.indice] m.indice=1; j++; } intercambiar(i, j); i++; } } O((n2-n)/2) O(1) i) (3/2)n j) 17 UNIVERSIDAD TÉCNICA FEDERICO SANTA MARÍA DEPARTAMENTO DE INFORMÁTICA EX UMBRA IN SOLEM 4.- (15 ptos.) Dada una lista de n elementos binarios se pide diseñar un procedimiento de complejidad O(n) que ordene la lista. RESP.: PseudoCodigo: NumCeros = Contar cuantos ceros hay en la lista; O(n) Para i=1 hasta NumCeros Escribir un cero en la lista de salida O(NumCeros<=n) Para i=NumCeros hasta n Escribir un UNO en la lista de salida O(n-NumCeros) Implementación: cont=0; for (i =1;i <= n; i++) if tabla[i]=0 cont++; for (i=1; i <= cont; i++) tabla[i] = 0; for (i =cont+1; i <= n; i++) tabla[i] = 1 PEOR CASO O(n) 5.- (30 ptos.) El editor de archivos secuenciales visto en clases tiene seis operaciones: Crear un nuevo archivo, insertar, reemplazar, eliminar, avanzar y retroceder, actuando siempre sobre el registro actual. La especificación en lenguaje natural de estas operaciones se describe a continuación: • Archivo_Nuevo (Archivo): Crea un archivo nuevo sin introducir ningún registro en él (número de registros es 0). • Insertar (Archivo, Registro): Inserta un registro después del registro actual y el nuevo pasa a ser el actual. • Reemplazar (Archivo, Registro): Cambia el registro actual por el nuevo. • Eliminar (Archivo): Borra el registro actual y una vez eliminado el actual pasa a ser el siguiente. • Avanzar (Archivo): El registro siguiente pasa a ser el actual. • Retroceder (Archivo): El registro anterior pasa a ser el actual. a.- Indique las excepciones de estas operaciones. b.- Impleméntelas en pseudocódigo o lenguaje C. c.- Determine la complejidad en cada caso. a.-) Excepciones: CONDICION - Insertar Archivo vacio - Reemplazar Archivo vacio - Eliminar Archivo vacio - Actual es el último - Avanzar Archivo vacio - Actual es el último - Retroceder Archivo vacio - Actual es el primero ACCION Inserta en la primera posición Nada Nada Borra y actual será el anterior Nada Nada Nada No hay registro actual La descripción del TDA en lenguaje de alto nivel no tiene porque tener en cuenta la eficiencia. UNIVERSIDAD TÉCNICA FEDERICO SANTA MARÍA DEPARTAMENTO DE INFORMÁTICA EX UMBRA IN SOLEM b.) Implementación: Archivo = ARRAY [1..n] OF INTEGER; Longitud: INTEGER; Reg_Actual: INTEGER; Implementación de las operaciones: Archivo_Nuevo (Archivo) { Longitud=0; Reg_Actual=0; } Insertar (Archivo,RegNuevo) { for (j=Longitud; j>= RegActual; j--) Archivo [j+1]=Archivo[j]; Archivo[RegActual+1]=RegNuevo; Longitud++; RegActual++; } Retroceder (Archivo) { if (RegActual != 0) RegActual --; } Eliminar (Archivo) { if (RegActual !=0 ) for (j=Actual; j <= Longitud-1; j++) Archivo[j]=Archivo[j+1]; if (RegActual >Longitud) RegActual --; } Avanzar (Archivo) { if( RegActual !=Longitud ) RegActual++; } Reemplazar (Archivo,RegNuevo) { if (RegActual !=0) Archivo[RegActual] = RegNuevo; } c.-) Complejidad: - Archivo_Nuevo () ---> O(1) - Insertar (Archivo) ---> O(n) - Reemplazar (Archivo, Registro) ---> O(1) - Eliminar (Archivo) ---> O(n) - Avanzar (Archivo) ---> O(1) - Retroceder (Archivo) ---> O(1) UNIVERSIDAD TÉCNICA FEDERICO SANTA MARÍA DEPARTAMENTO DE INFORMÁTICA EX UMBRA IN SOLEM 6.- (25 ptos.) Dado el siguiente procedimiento recursivo. Calcular el número de llamadas que se harán al procedimiento recursivo en función de n. Si en el punto * p * la pila interna del sistema tiene capacidad para almacenar un máximo de 32405 bytes y suponiendo que la dirección de retorno de un procedimiento ocupa 4 bytes y una variable entera ocupa 2 bytes, entonces calcule el valor máximo de n para el que se pueda ejecutar la llamada p(n) sin que se desborde la pila. Justifique sus respuestas. function p(int n) function Recursivo (int m,n) int i; { Si m >1 entonces Si n>1 entonces Recursivo(m,n-1) sino Recursivo (m-1,m-1); i:=m*n; write(i); } main { Si n >=1 entonces { // * p * Recursivo(n, n); write('fin') } } RESP.: La llamada ocupa 8 bytes (4 bytes la dirección de retorno mas 4 bytes por las variables de entrada (m y n)), mas 2 bytes de la variable local (i). Cada llamada recursiva ocupa en total 10 bytes en la pila. a) Cuando m = n = 1 se acaba la recursividad. b) Cuando m>1 y n>1 realiza la recursividad (m, n-1) c) Cuando m>1 y n=1 realiza la recursividad (m-1,m-1) Al realizar la primera llamada con n tenemos: (n,n) +---> (n-1, n-1) +---> (n-2, n-2) (n,n-1) | (n-1, n-2) | (n-2, n-3) (n,n-2) | (n-1, n-3) | ... ... | ... | Hasta que ---------- --------------------(n, 1) ---+ (n-1, 1) ---+ lo que da la siguiente sucesión de llamadas: n + (n-1) + (n-2) + 2 SUM(i) = (n+1)*(n/2) = (n +n)/2 (Número de llamadas)*10 bytes <= 32405 5*(n2+n) <= 32405 n = 80 ( 1, 1) 1