Examen de Programación 2

Anuncio
Instituto de Computación - Facultad de Ingeniería - Universidad de la República
Examen de Programación 2
Julio de 2011
Generalidades:
•
•
•
•
•
•
•
La prueba es individual y sin material; duración: 3hs.
Sólo se contestan dudas acerca de la letra de los ejercicios.
Escriba las hojas de un sólo lado y con letra clara.
Resuelva ejercicios diferentes en hojas diferentes.
Numere cada hoja, indicando en la primera el total.
Coloque su nro. de cédula y nombre en cada hoja.
Se permite usar funciones y procedimientos auxiliares en todos los ejercicios, excepto en aquellos en los que se
indique lo contrario.
Ejercicio 1 (20 puntos)
Considere la siguiente declaración, en Módula-2, del tipo de las listas de números enteros LInt:
TYPE
LInt = POINTER TO RECORD
info : INTEGER;
sig : LInt
END;
Se pide, sin usar funciones o procedimientos auxiliares y accediendo directamente a la representación, implementar la
siguiente función iterativa:
Inv: Dada una lista L de enteros de tipo Lint, retorna una nueva lista (que no comparte registros de memoria con la
lista parámetro) que contiene todos los elementos de L, excepto el primero y el último, pero en orden inverso. Si L está
vacía la función deberá retornar la lista vacía.
Ejemplos:
Entradas
Resultado de Inv
L = [3,2,7,1,8,5]
[8,1,7,2]
L = [2,4]
[]
L = [2]
[]
L = []
[]
SOLUCION
PROCEDURE Inv ( l : Lint ) : Lint;
VAR lstRes, ptrNuevo : Lint;
BEGIN
lstRes := NIL;
IF (l <> NIL) AND (l^.sig <> NIL) THEN
l := l^.sig;
WHILE (l^.sig <> NIL) DO
New(ptrNuevo);
ptrNuevo^.info := l^.info;
ptrNuevo^.sig := lstRes;
lstRes := ptrNuevo;
l := l^.sig;
END;
END;
RETURN lstRes;
END Inv;
Instituto de Computación - Facultad de Ingeniería - Universidad de la República
Ejercicio 2. (35 puntos)
Para trabajar con árboles balanceados es útil guardar en cada nodo información para verificar condiciones de equilibrio.
Por ejemplo, en los árboles llamados AVL (que son ABB balanceados) puede guardarse en cada nodo la altura del árbol
que tiene a dicho nodo como raíz.
En la siguiente figura se puede ver un ejemplo de la información que poseen los nodos de esta clase de árboles:
6
h=2
h=1
h=0
2
h=3
3
9
4
h=0
h=1
10
h=0
1
Se pide, utilizando la siguiente definición de los árboles binarios de búsqueda de enteros, con información de la altura
en cada nodo:
ABB = POINTER TO ABBNodo;
ABBNodo = RECORD
info: INTEGER;
altura: CARDINAL;
izq, der: ABB;
END;
a) Implementar un procedimiento que dado un ABB de enteros que guarda en cada nodo, además del dato, el valor de
su altura, y dado un entero, inserte a dicho elemento en el ABB (si ya no estaba) manteniendo la información de la
altura de cada nodo. Notar que no se pide balancear el árbol, sino simplemente insertar el elemento en el ABB
dejando en cada nodo en el campo altura el valor correspondiente, asumiendo que el árbol parámetro guarda en el
campo altura de cada nodo el valor correcto. Este procedimiento no puede usar funciones ni procedimientos
auxiliares.
b) Implemente una función booleana que retorne TRUE si y sólo si un ABB (del tipo definido anteriormente) es un
AVL. Esto es, se cumple que para cada nodo del árbol la altura de sus subárboles izquierdo y derecho difiere a lo
sumo en 1. El árbol vacío es un AVL. Esta función no puede usar funciones ni procedimientos auxiliares.
c) Indique los órdenes de tiempo de ejecución en el peor caso del procedimiento definido en la parte (a) y de la función
definida en la parte (b). Justifique brevemente.
SOLUCION
a)
PROCEDURE Insertar (VAR t : ABB; x : INTEGER);
BEGIN
IF (t = NIL) THEN
NEW(t);
t^.info := x;
t^.altura := 0;
t^.izq := NIL;
t^.der := NIL
ELSIF (x < t^.info) THEN
Insertar(t^.izq, x);
Instituto de Computación - Facultad de Ingeniería - Universidad de la República
IF (t^.altura = t^.izq^.altura) THEN
t^.altura := t^.altura + 1
END
ELSIF (x > t^.info) THEN
Insertar(t^.der, x);
IF (t^.altura = t^.der^.altura) THEN
t^.altura := t^.altura + 1
END
END
END Insertar;
b)
PROCEDURE EsAVL (t : ABB) : BOOLEAN;
BEGIN
IF (t = NIL) OR ((t^.izq = NIL) AND (t^.der = NIL)) THEN
RETURN TRUE
ELSIF (t^.izq = NIL) THEN
RETURN (t^.der^.altura = 0)
ELSIF (t^.der = NIL) THEN
RETURN (t^.izq^.altura = 0)
ELSE RETURN (ABS(t^.izq^.altura – t^.der^.altura) <= 1)
AND EsAVL(t^.izq) AND EsAVL(t^.der)
END
END EsAVL;
c)
El procedimiento Insertar es O(n) de tiempo de ejecución en el peor caso, siendo n la
cantidad de nodos del árbol. El peor caso se da cuando la inserción se produce en un
camino que tiene a todos los nodos del árbol (el árbol degenera en una lista).
La función EsAVL es O(n) de tiempo de ejecución en el peor caso, siendo n la cantidad de
nodos del árbol. La función recorre todo el árbol y si éste es efectivamente un AVL,
todos los nodos serán visitados (considerados) una vez.
Ejercicio 3. (45 puntos)
a) De una especificación de un TAD Cola de Prioridad no acotada de elementos de un tipo genérico T donde las
prioridades estén dadas por números naturales y que permita obtener, y eliminar, elementos tanto de mínima como
de máxima prioridad. Considere un conjunto mínimo de operaciones constructoras, selectoras/destructoras (Min,
BorrarMin, Max, BorrarMax) y predicados. Tenga en cuenta que pueden haber elementos de igual prioridad y que
las operaciones selectoras/destructoras consideran el orden de llegada frente a elementos de igual prioridad.
b) Desarrolle una implementación del TAD anterior donde las operaciones selectoras Min y Max, las operaciones
constructoras y los predicados tengan O(1) de tiempo de ejecución en el peor caso. Se debe dar una representación e
implementar las operaciones constructoras, las selectoras/destructoras Min y BorrarMin, y los predicados. Omita el
código de Max y Borrar Max. No se permite usar TADs auxiliares en este ejercicio.
c) ¿Qué varía en la especificación de la parte a) si la Cola de Prioridad es acotada?. Detalle brevemente.
¿Qué varía en la implementación de la parte b) si la Cola de Prioridad es acotada y se debe satisfacer igualmente
la restricción de orden de tiempo de ejecución impuesta a ciertas operaciones del TAD?. Detalle brevemente (no se
pide desarrollar código).
d) Dos Colas de Prioridad son iguales si son indistinguibles a través de sus operaciones selectoras/destructoras.
Desarrolle una función que dadas dos Colas de Prioridad de acuerdo a la especificación dada en la parte a), retorne
TRUE si y sólo si éstas son iguales. Asuma que los elementos de tipo T son comparables con el operador “=”. La
función puede modificar las colas de prioridad parámetros.
Instituto de Computación - Facultad de Ingeniería - Universidad de la República
SOLUCION
a)
PROCEDURE EmptyPQ (VAR pq: PQ);
(* Construye la cola de prioridad vacía *)
PROCEDURE IsEmptyPQ (pq: PQ; VAR empty: Boolean);
(* Retorna TRUE si pq es vacía y FALSE en caso contrario *)
PROCEDURE InsertPQ (t: T; p: Cardinal; VAR pq: PQ);
(* Inserta el elemento t con prioridad p en la cola pq *)
PROCEDURE Min (pq: PQ; VAR min: T);
(* PRE: NOT IsEmpty(pq). Retorna el elemento de pq con prioridad mínima, teniendo en
cuenta el orden FIFO en caso de elementos de igual prioridad *)
PROCEDURE Max (pq: PQ; VAR max: T);
(* PRE: NOT IsEmpty(pq). Retorna el elemento de pq con prioridad máxima, teniendo en
cuenta el orden FIFO en caso de elementos de igual prioridad *)
PROCEDURE BorrarMin (VAR pq: PQ);
(* PRE: NOT IsEmpty(pq). Elimina de pq el elemento con prioridad mínima, teniendo en
cuenta el orden FIFO en caso de elementos de igual prioridad *)
PROCEDURE BorrarMax (VAR pq: PQ);
(* PRE: NOT IsEmpty(pq). Elimina de pq el elemento con prioridad máxima, teniendo en
cuenta el orden FIFO en caso de elementos de igual prioridad *)
(* Podría incluirse una destructora del TAD que libere toda la memoria de una cola de
prioridad. En este caso la omitimos asumiendo que puede definirse por fuera del TAD a
partir de las existentes *)
b)
(*
Lista simplemente encadenada con punteros al mínimo y máximo, teniendo en cuenta el orden
FIFO en caso de elementos de igual prioridad. Las inserciones se realizan siempre al
comienzo de la lista.
*)
TYPE
List = POINTER TO ListNode;
ListNode = RECORD
value: T;
prior: CARDINAL;
sig: List;
END;
PQ = POINTER TO PQNode;
PQNode = RECORD
min, max: List;
values: List;
END;
PROCEDURE EmptyPQ
BEGIN
NEW(pq);
pq^.min :=
pq^.max :=
pq^.values
END EmptyPQ;
(VAR pq : PQ);
NIL;
NIL;
:= NIL;
PROCEDURE IsEmptyPQ (pq: PQ; VAR empty: Boolean);
BEGIN
empty := (pq^.values = NIL);
END IsEmptyPQ;
Instituto de Computación - Facultad de Ingeniería - Universidad de la República
PROCEDURE InsertPQ (t: T; p: Cardinal; VAR pq: PQ);
VAR elem : List;
BEGIN
NEW(elem);
elem^.value := t;
elem^.prior := p;
elem^.sig := pq^.values;
pq^.values := elem;
(* mantengo el orden de los repetidos según la política FIFO *)
IF ((pq^.min = NIL) OR (pq^.min^.prior > p)) THEN
pq^.min = elem;
END;
(* mantengo el orden de los repetidos según la política FIFO *)
IF ((pq^.max = NIL) OR (pq^.max^.prior < p)) THEN
pq^.max = elem;
END;
END;
PROCEDURE Min (pq: PQ; VAR min: T);
BEGIN
min := pq^.min^.value;
END Min;
(* Auxiliar de BorrarMin *)
PROCEDURE BorrarNodoMin (VAR pq: PQ);
(* PRE: NOT IsEmpty(pq). Elimina de pq el nodo con el elemento de prioridad mínima,
teniendo en cuenta el orden FIFO en caso de elementos de igual prioridad. pq^.min y
eventualmente pq^.max quedan indefinidos *)
VAR lista: List;
BEGIN
lista := pq^.values;
IF (pq^.min = lista) THEN (* Si es el primero *)
pq^.values := pq^.values^.sig;
ELSE
WHILE (lista^.sig <> pq^.min) DO
lista := lista^.sig;
END;
lista^.sig := lista^.sig^.sig;
END;
DISPOSE(pq^.min);
END BorrarNodoMin;
(* Auxiliar de BorrarMin *)
PROCEDURE EstablecerMinMax (VAR pq: PQ);
(* Establece los punteros a los elementos de prioridad mínima y máxima de pq, teniendo en
cuenta el orden FIFO en caso de elementos de igual prioridad *)
VAR lista, PunteroMin, PunteroMax: List;
BEGIN
lista := pq^.values;
PunteroMin:= lista;
PunteroMax:= lista;
WHILE (lista <> NIL) DO
IF (lista^.prior <= PunteroMin^.prior) THEN
PunteroMin := lista;
END;
IF (lista^.prior >= PunteroMax^.prior) THEN
PunteroMax := lista;
END;
lista := lista^.sig;
END;
pq^.min := PunteroMin;
pq^.max := PunteroMax;
END EstablecerMinMax;
Instituto de Computación - Facultad de Ingeniería - Universidad de la República
PROCEDURE BorrarMin (VAR pq : PQ);
BEGIN
BorrarNodoMin(pq);
EstablecerMinMax(pq);
END BorrarMin;
c)
Parte i)
•
•
Requiere agregar un predicado que permita saber si la PQ está llena.
PROCEDURE IsFullPQ (pq: PQ; VAR full: Boolean);
(* Retorna TRUE si pq esta llena y FALSE en caso contrario *)
Requiere agregar la siguiente precondición al procedimiento InsertPQ: PRE: NOT
IsFull(pq).
Parte ii)
•
Requiere incorporar en la estructura un contador para saber cuantos elementos hay
y evitar de esta manera tener que recorrer la estructura en el código del
procedimiento IsFullPQ.
d)
PROCEDURE Iguales(pq1, pq2: PQ) : BOOLEAN;
VAR
e1, e2 : BOOLEAN;
min1, min2 : T;
BEGIN
IsEmptyPQ(pq1, e1);
IsEmptyPQ(pq1, e2);
IF (e1 AND e2) THEN
RETURN TRUE;
ELSIF (NOT(e1) AND NOT(e2)) THEN
Min(pq1, min1);
Min(pq2, min2);
BorrarMin(pq1);
BorrarMin(pq2);
RETURN ((min1 = min2) AND Iguales(pq1, pq2));
ELSE RETURN FALSE;
END;
END Iguales;
Descargar