Convocatoria: Septiembre 2004 Estructuras de datos II. 1 Estructuras de datos II Convocatoria: Septiembre 2004 Dpto. LSIIS. Unidad de Programación Normas Duración: El examen se compone de 1 ejercicio y una colección de preguntas cortas. Su duración será de dos horas. Transcurridos 45 minutos del comienzo del examen se recogerán las preguntas cortas. Entrega: las preguntas cortas deben responderse en la misma hoja del examen. Calificaciones: Las calificaciones se publicarán en el tablón de anuncios de la asignatura el dı́a 14 de Septiembre de 2004. Soluciones: Las soluciones a los ejercicios se publicarán en el tablón de la asignatura junto con las notas. 1. Preguntas cortas [6 puntos] Nombre: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Número de matrı́cula: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Grupo: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Esta hoja se deberá rellenar con los datos del alumno y entregar como parte del examen. Todas las preguntas tienen la misma puntuación. Las preguntas tipo test tienen únicamente una respuesta válida y las respuestas incorrectas restan 0.5 puntos. El resto de preguntas no descuentan puntuación si se responden de manera incorrecta. 1. El algoritmo de ordenación de ficheros secuenciales por mezcla de tramos crecientes de tamaño máximo (mezcla natural ), se estructura en etapas consistentes en dos fases, una de “reparto” de tramos entre dos o más ficheros secuenciales auxiliares, y otra fase de “mezcla” de tramos. ¿Cuál es el número máximo de etapas que es necesario ejecutar si el fichero a ordenar tiene n registros y se utilizan dos ficheros auxiliares? RESPUESTA: 2. log2 n Supóngase una empresa en la que cada empleado está adscrito a un departamento pero en cada departamento puede haber muchos miembros. La relación que se establece entre los empleados y los departamentos es: [X] Uno a muchos [ ] Muchos a muchos [ ] No tiene por que haber relación [ ] Uno a uno 3. Para implementar de forma iterativa los recorridos en profundidad y anchura de un grafo utilizaremos como estructura de datos auxiliar respectivamente: [ ] una cola y una pila. [X] una pila y una cola. [ ] pila para ambos tipos de recorrido. [ ] una cola y una lista. Convocatoria: Septiembre 2004 Estructuras de datos II. 4. 2 El recorrido en profundidad de un grafo no dirigido garantiza que se visitan todos los nodos del grafo: [ ] en cualquier caso [ ] si el nodo escogido para iniciar la búsqueda en profundidad es el adecuado. [X] si el grafo es conexo. [ ] ninguna de estas opciones. 5. Dado un montı́culo binario implementado sobre un array. ¿En qué posición del array se encuentra el nodo padre de un nodo que se encuentra en la posición n del array? ¿Cuál es el orden de complejidad en el peor caso de la operación de acceso al nodo padre? RESPUESTA: El padre de un nodo n se encuentra en la posición parte entera(n/2). El tiempo de acceso al nodo padre tiene complejidad O(1) (constante) ya que el cálculo de la posición del padre tiene complejidad constante y también es constante el tiempo de acceso a una posición de un array. 6. Dado el siguiente código Ada, indı́quese cúal serı́a el resultado de la ejecución de dicho código. with Ada . D i r e c t I O ; with Ada . I n t e g e r T e x t I O ; procedure U s a F i c h e r o D i r e c t o i s package F i c h e r o A u x i l i a r i s new Ada . D i r e c t I O ( I n t e g e r ) ; use F i c h e r o A u x i l i a r ; Fichero : File Type ; Dato : Integer ; Tamaño : Count ; Posicion : Positive Count ; begin C r e a t e ( F i c h e r o , I n O u t F i l e , ” aux ” ) ; Write ( Fichero , 100 , 1 0 ) ; Tamaño := S i z e ( F i c h e r o ) ; P o s i c i o n := Tamaño / 2 ; Set Index ( Fichero , Posicion ) ; f o r I in reverse 1 . . P o s i c i o n loop Write ( Fichero , I n t e g e r ( I ) ∗ 1 0 ) ; end loop ; Reset ( Fichero ) ; while not E n d O f F i l e ( F i c h e r o ) loop Read ( F i c h e r o , Dato ) ; Ada . I n t e g e r T e x t I O . Put ( Dato , 4 ) ; end loop ; Close ( Fichero ) ; end U s a F i c h e r o D i r e c t o ; RESPUESTA: 0 0 0 0 50 40 30 20 10 100 Estructuras de datos II. 2. Convocatoria: Septiembre 2004 Matrices de adyacencia simétricas y dispersas 3 [4 puntos] Las matrices de adyacencia se utilizan para representar los arcos de un grafo mediante una matriz booleana cuyas dimensiones son Card(Tipo Nodo) x Card(Tipo Nodo). Esta representación puede no ser Card(Arcos(G)) eficiente en memoria. Definimos el grado de conexión de un grafo G como (Card(T ipo N odo))2 . Dicho grado está comprendido para todo grafo entre 0 y 1. Si el grado de conexión de un grafo es cercano a 0 las matrices de adyacencia no son eficientes en memoria. Para los grafos no dirigidos es habitual utilizar una matriz simétrica con el objeto de reducir el consumo de memoria de esta representación. Para grafos con grado de conexión bajo, una optimización posible consiste en la utilización de matrices dispersas. Una forma posible de implementar matrices dispersas consiste en utilizar el TAD tabla de la siguiente manera: tomamos como claves de la tabla los posibles arcos (pares de nodos) del grafo, y la información asociada a cada clave (arco) es el booleano cierto. una casilla de la matriz tiene el valor cierto (existe un arco entre dos nodos de un grafo) si y solo si existe una entrada en la tabla para ese par de nodos. Al ser una matriz de booleanos, el valor de la información asociada a una clave es en realidad irrelevante. La ventaja de esta representación de matrices dispersas es que no se guarda información en la tabla para aquellos pares de nodos entre los que no existe ningún arco, sino solamente para los que efectivamente hay un arco. Para eliminar un arco se elimina de la tabla la entrada correspondiente. En nuestro caso utilizaremos la implementación de tablas basada en árboles AVL. Se muestra a continuación la parte privada del fichero grafos.ads utilizando la implementación propuesta. private package A d y a c e n c i a i s new T a b l a s ( T i p o C l a v e => T i p o A r c o , T i p o I n f o r m a c i o n => Boolean , ”<” => ”<” ) ; use A d y a c e n c i a ; type V e c t o r N o d o s i s array ( Tipo Nodo ) of B o o l e a n ; type T i p o G r a f o i s record Nodos : V e c t o r N o d o s := ( others => F a l s e ) ; M a t r i z A d y a c e n c i a : Ta b l a ; −− M a t r i z A d y a c e n c i a : M a t r i z ; end record ; end G r a f o s ; La principal diferencia entre este código y el visto en clase para grafos no dirigidos radica en la utilización del paquete genérico tablas, en vez del paquete genérico de matrices simétricas. Para instanciar el paquete genérico de tablas necesitamos proporcionar una relación de orden entre claves. La relación utilizada es la siguiente: function ”<” ( A1 : T i p o A r c o ; A2 : T i p o A r c o ) return B o o l e a n i s begin return A1 . Nodo1 < A2 . Nodo1 or e l s e ( A1 . Nodo1 = A2 . Nodo1 and then A1 . Nodo2 < A2 . Nodo2 ) ; end ”<” ; Adicionalmente, como la matriz que queremos representar es simétrica, almacenaremos únicamente la matriz triangular inferior. Para ello, utilizaremos la función Posición siguiente: function P o s i c i ó n ( F i l a , Columna : Tipo Nodo ) return T i p o A r c o i s Arco : T i p o A r c o ; begin i f F i l a >= Columna then Arco := ( F i l a , Columna ) ; else Arco := ( Columna , F i l a ) ; end i f ; return Arco ; end P o s i c i ó n ; Estructuras de datos II. Convocatoria: Septiembre 2004 4 Las operaciones requeridas trabajan con los TADs Conjunto y Tablas vistos en clase. Recordamos a continuación su interfaz: generic type T i p o E l e m e n t o i s private ; package C o n j u n t o s i s type C o n j u n t o i s private ; function V a c i o return C o n j u n t o ; function E s V a c i o (C : C o n j u n t o ) return B o o l e a n ; function P e r t e n e c e (C : C o n j u n t o ; E l t o : T i p o E l e m e n t o ) return B o o l e a n ; function I n s e r t a r ( E : T i p o E l e m e n t o ; C : C o n j u n t o ) return C o n j u n t o ; function E x t r a e r (C : C o n j u n t o ) return T i p o E l e m e n t o ; function B o r r a r ( E : T i p o E l e m e n t o ; C : C o n j u n t o ) return C o n j u n t o ; function C o p i a r ( C1 : C o n j u n t o ) return C o n j u n t o ; procedure D e s t r u i r (C : in out C o n j u n t o ) ; end C o n j u n t o s ; −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−− generic type T i p o C l a v e i s private ; type T i p o I n f o r m a c i o n i s private ; with function ”<” ( I z d a , Dcha : T i p o C l a v e ) return B o o l e a n ; package T a b l a s i s type T abla i s limited private ; procedure C r e a r V a c i a (T : out T a b l a ) ; function E s V a c i a (T : in Ta b l a ) return B o o l e a n ; function E s t a L l e n a (T : in T a b l a ) return B o o l e a n ; function E s t a (T : in Tabla ; C l a v e : in T i p o C l a v e ) return B o o l e a n ; procedure Almacenar (T : in out T a b l a ; C l a v e : in T i p o C l a v e ; I n f o : in T i p o I n f o r m a c i o n ) ; function C o n s u l t a (T : in Ta b l a ; C l a v e : in T i p o C l a v e ) return T i p o I n f o r m a c i o n ; procedure B o r r a r (T : in out T a b l a ; C l a v e : in T i p o C l a v e ) ; procedure D e s t r u i r (T : in out T a b l a ) ; type T i p o A c c i o n i s access procedure ( C l a v e : in T i p o C l a v e ; I n f o : in T i p o I n f o r m a c i o n ) ; procedure R e c o r r e r (T : in T a b l a ; A c c i o n : in T i p o A c c i o n ) ; procedure A s i g n a r ( T1 : out T a b l a ; T2 : in T a b l a ) ; end T a b l a s ; Se pide: 1. Realizar en Ada la implementación de las operaciones Borrar Nodo y Adyacentes cuyas cabeceras son: procedure B o r r a r N o d o ( G r a f o : in out T i p o G r a f o ; Nodo : Tipo Nodo ) ; function A d y a c e n t e s ( G r a f o : T i p o G r a f o ; Nodo : Tipo Nodo ) return C j t o N . C o n j u n t o ; SOLUCION: procedure B o r r a r N o d o ( G r a f o : in out T i p o G r a f o ; Nodo : in Tipo Nodo ) is Arco : T i p o A r c o ; begin G r a f o . Nodos ( Nodo ) := F a l s e ; f or C o l in Tipo Nodo loop Arco := P o s i c i ó n ( Nodo , C o l ) ; B o r r a r ( G r a f o . M a t r i z A d y a c e n c i a , Arco ) ; end loop ; end B o r r a r N o d o ; Estructuras de datos II. Convocatoria: Septiembre 2004 5 function A d y a c e n t e s ( G r a f o : T i p o G r a f o ; Nodo : Tipo Nodo ) return C j t o N . C o n j u n t o is C j t o N o d o s : C j t o N . C o n j u n t o := C j t o N . V a c i o ; Arco : T i p o A r c o ; begin i f G r a f o . Nodos ( Nodo ) then for C o l in Tipo Nodo loop Arco := P o s i c i ó n ( Nodo , C o l ) ; i f E s t a ( G r a f o . M a t r i z A d y a c e n c i a , Arco ) then C j t o N o d o s := C j t o N . I n s e r t a r ( Col , C j t o N o d o s ) ; end i f ; end loop ; end i f ; return C j t o N o d o s ; end A d y a c e n t e s ; 2. Rellénese la tabla mostrada a continuación con el grado de complejidad en tiempo en el peor caso de las operaciones anteriormente implementadas. ¿Ha mejorado o empeorado la complejidad en tiempo con respecto a la implementación inicial? ¿Por qué? Para realizar este análisis, considérese que la operación de inserción de un elemento en un conjunto tiene complejidad constante. Borrar Nodo Adyacentes Matrices de adyacencia simétricas O(Card(T ipo N odo) O(Card(T ipo N odo) Matrices de adyacencia simétricas y dispersas O(Card(T ipo N odo) × log (Card(Arcos(G)))) O(Card(T ipo N odo) × log (Card(Arcos(G)))) La eficiencia en tiempo ha empeorado respecto de la implementación inicial porque el uso de tablas AVL ha hecho que el tiempo de acceso para determinar si existe o no un arco entre dos nodos pase de complejidad constante a complejidad logarı́tmica en el número de arcos que tenga el grafo en un momento dado (Card(Arcos(G)).