Instituto de Computación - Facultad de Ingeniería - Universidad de la República Examen de Programación 2 Diciembre de 2009 Ejercicio 1. (20 puntos) Considere la siguiente declaración, en MÓDULA-2, del tipo ListaEnt de listas encadenadas de enteros: ListaEnt = POINTER TO NodoEnt; NodoEnt = RECORD info: INTEGER; sig: ListaEnt; END; Defina un procedimiento iterativo EliminarRepetidos en MÓDULA-2 que dada una lista de enteros ordenada de menor a mayor borre físicamente todas las ocurrencias de elementos repetidos en la lista, dejando únicamente una ocurrencia de cada elemento (se deberá invocar DISPOSE para liberar la memoria). La lista resultado debe también estar ordenada de menor a mayor. Si la lista es vacía el procedimiento no tendrá efecto. Por ejemplo, si la lista es [1,4,4,7,8,8,8,9], luego de ejecutar EliminarRepetidos, la lista debería ser: [1,4,7,8,9]. El procedimiento EliminarRepetidos debe recorre a lo sumo una vez la lista parámetro. No se permite usar TADs en este ejercicio ni funciones o procedimientos auxiliares. PROCEDURE EliminarRepetidos(lista : ListaEnt); VAR aBorrar : ListaEnt; BEGIN IF (lista<>NIL) THEN WHILE (lista^.sig <> NIL) DO IF (lista^.info = lista^.sig^.info) THEN (*si el nodo siguiente es igual al actual lo elimino*) aBorrar := lista^.sig; lista^.sig := lista^.sig^.sig; DISPOSE(aBorrar) ELSE (*si son distintos continuo recorriendo*) lista := lista^.sig END END END END EliminarRepetidos; Ejercicio 2. (35 puntos) Considere la siguiente declaración, en MÓDULA-2, del tipo AB de árboles binarios de enteros: AB = POINTER TO ABNode; ABNode = RECORD info: INTEGER; left: AB; right: AB; END; a) Considere además la definición de la función f que sigue: Instituto de Computación - Facultad de Ingeniería - Universidad de la República PROCEDURE f(t: AB; k:INTEGER): BOOLEAN; BEGIN IF t = NIL THEN RETURN (k=0) ELSE RETURN (f(t^.left,k-1) AND f(t^.right,k-1)) END f; 1. ¿Qué retorna la función f ?. Retorna TRUE si en el árbol todos los caminos de la raíz a una hoja tienen k elementos, y FALSE en caso contrario. Esto es, el árbol está perfectamente balanceado y posee altura k. 2. ¿Cuántos nodos tiene el árbol si la función retorna TRUE?. Justifique. 2k-1, ya que es la cantidad de nodos es ∑i=0..k-1 2i. b) Defina una función que dado un árbol binario de tipo AB retorne TRUE si el árbol cumple la propiedad de orden de un Heap. Asumimos que un Heap puede contener elementos repetidos. No se permite usar TADs en este ejercicio. Considerando de mayor prioridad al entero más grande. PROCEDURE esHeap (t: AB): BOOLEAN; BEGIN IF (t = NIL) THEN RETURN TRUE ELSIF (t^.left = NIL) THEN IF (t^.right = NIL) RETURN TRUE ELSE RETURN((t^.info <= t^.right^.info) AND esHeap (t^.right)) ELSIF (t^.right = NIL) RETURN ((t^.info <= t^.left^.info) AND esHeap (t^.left)) ELSE RETURN ((t^.info <= t^.right^.info) AND (t^.info <= t^.left^.info) AND esHeap (t^.right) AND esHeap (t^.left)) END END esHeap; Ejercicio 3. (45 puntos) a) Especificar en MODULA-2 un TAD que permita trabajar con relaciones binarias, no acotadas, de elementos de dos tipos genéricos S y T. Considerar operaciones constructoras, selectoras/destructoras y predicados, además de las siguientes operaciones adicionales: Imagenes (x,R) = { y∈T | (x,y)∈R }. PreImagenes (y,R) = { x∈S | (x,y)∈R }. EsFuncional (R). Retorna TRUE si y sólo si R es una relación funcional. b) Desarrollar una implementación completa del TAD anterior. Ejercicio 3: a) DEFINITION MODULE RELBinST; TYPE RELBinST; Instituto de Computación - Facultad de Ingeniería - Universidad de la República PROCEDURE CrearRel():RELBinST; (* Crea la Relación Binaria de elementos S x T vacía.*) PROCEDURE AgregarRel(p: ParST; R: RELBinST): RELBinST; (* Agrega a la Relación Binaria R de elementos S x T el par p. Precondición: p no pertenece a R *) PROCEDURE EsVaciaRel(R: RELBinST): BOOLEAN; (* Retorna TRUE si y solo si la Relación Binaria R es vacía. *) PROCEDURE ObtenerPar(R: RELBinST): ParST; (* Obtiene un par S x T perteneciente a la Relación Binaria R. *) (* Pre-condición: R no es vacía. *) PROCEDURE SacarRel(R: RELBinST): RELBinST; (* Elimina un par S x T perteneciente a la Relación Binaria R. *) (* Pre-condición: R no es vacía. *) PROCEDURE Imagenes(x: S; R: RELBinST): ListaT; (* Devuelve la lista con las imágenes de x en la Relación R.*) PROCEDURE PreImagenes(y: T; R: RELBinST): ListaS; (* Devuelve la lista con las preimágenes de y en la Relación R.*) PROCEDURE EsFuncional(R: RELBinST): Boolean; (* Devuelve TRUE si la Relación Binaria R es una relación funcional.*) END RELBinST. NOTA: podrían usarse conjuntos en vez de listas para trabajar con las imágenes y pre-imágenes de los elementos. (* Tads Auxiliares *) DEFINITION MODULE ParST; TYPE ParST; PROCEDURE CrearPar(x: S; y: T):ParST; (* Crea el par de elementos (x y). *) PROCEDURE ObtenerS(p: ParST): S; (* Obtiene la componente en S de un par S x T. *) PROCEDURE ObtenerT(p: ParST): T; (* Obtiene la componente en T de un par S x T. *) END ParST. DEFINITION MODULE ListaGen; TYPE ListaGen; PROCEDURE Vacia(): ListaGen; (* Retorna la lista vacía. *) PROCEDURE Cons (n : Gen; s : ListaGen): ListaGen; (* Retorna la lista con el elemento n. *) Instituto de Computación - Facultad de Ingeniería - Universidad de la República PROCEDURE esVacia (s : ListaGen): BOOLEAN; (* Retorna TRUE si s es vacía. *) PROCEDURE Primero (s : ListaGen): Gen; (* Precondición: s no vacía, retorna: el primer elemento de s. *) PROCEDURE Cola (s : ListaGen): ListaGen; (* Precondición: s no vacía, retorna la lista s sin el primer elemento. *) END ListaGen. b) Para implementar el TAD se utilizará una lista no ordenada. IMPLEMENTATION MODULE RELBinST; TYPE RELBinST = POINTER TO Nodo; Nodo = RECORD info: ParST; sig: RELBinST; END; PROCEDURE CrearRel():RELBinST; BEGIN RETURN (NIL) END CrearRel; PROCEDURE AgregarRel(p: ParST; R: RELBinST): RELBinST; VAR aux: RELBinST; BEGIN New(aux); aux^.info := p; aux^.sig := R; Return (aux) END AgregarRel; PROCEDURE EsVaciaRel(R: RELBinST): BOOLEAN; BEGIN RETURN (R=NIL) END EsVaciaRel; PROCEDURE ObtenerPar(R: RELBinST): ParST; BEGIN RETURN (R^.info) END ObtenerPar; PROCEDURE SacarRel(R: RELBinST): RELBinST; BEGIN RETURN (R^.sig) END SacarRel; PROCEDURE Imagenes(x: S; R: RELBinST): ListaT; VAR acum: ListaT; BEGIN acum := Vacia(); WHILE R<>NIL Instituto de Computación - Facultad de Ingeniería - Universidad de la República IF ObtenerS(R^.info) = x THEN acum := Cons(ObtenerT(R^.info),acum) END R := R^.sig; END RETURN acum; END Imagenes; PROCEDURE PreImagenes(y: T; R: RELBinST): ListaS; VAR acum: ListaS; BEGIN acum := Vacia(); WHILE R<>NIL IF ObtenerT(R^.info) = y THEN acum := Cons(ObtenerS(R^.info),acum) END R := R^.sig; END RETURN acum; END PreImagenes; PROCEDURE EsFuncional(R: RELBinST): Boolean; VAR acum: ListaT; x: S; funcion: Boolean; BEGIN funcion := TRUE; WHILE R<>NIL AND funcion x := ObtenerS(R^.info); acum := Imagenes(x,R^.sig); funcion := esvacia(acum); R := R^.sig; END; RETURN funcion; END EsFuncional; END ListaGen.