Solución de Examen de Programación 2

Anuncio
Solución de Examen de Programación 2
Diciembre de 2013
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.
Ejercicio 1 ( 50 puntos)
Considere las siguientes definiciones:
TYPE
ListaNat = POINTER TO LNodo;
LNodo
= RECORD
elem: CARDINAL;
sig: ListaNat;
END;
ABNat
ABNodo
= POINTER TO ABNodo;
= RECORD
nodo: CARDINAL;
izq,der: ABNat;
END;
Implemente en Modula-2 y utilizando recursión las siguientes funciones:
1. Una función InsOrd, que dados un natural y una lista ListaNat ordenada (creciente) inserte el
natural en la lista manteniendo su orden. La lista resultante comparte memoria con la lista
pasada como parámetro.
PROCEDURE InsOrd (e : CARDINAL; l : ListaNat): ListaNat;
2. Una función GenerarListaOrd, que dado un árbol binario de naturales ABNat retorne una lista
ListaNat ordenada (creciente) con todos los elementos del árbol. No se puede acceder a la
estructura de la lista, para construirla sólo se puede utilizar NIL (lista vacía) y la función de la
parte anterior.
PROCEDURE GenerarListaOrd (a : ABNat): ListaNat;
3. Una función Ordenar, que dado un árbol binario de naturales ABNat retorne otro árbol que tenga
la misma forma y los mismos elementos, pero que sea un árbol binario de búsqueda. El árbol
resultante no comparte memoria con el árbol pasado como parámetro. Si utiliza funciones
auxiliares debe implementarlas.
PROCEDURE Ordenar (a : ABNat): ABNat;
NOTA: en caso de utilizarse funciones auxiliares estas deben ser implementadas
Ejercicio 2 (50 puntos)
Se desea utilizar una Tabla para guardar información de contactos telefónicos en forma de
correspondencias entre Nombres y Télefonos. Los Nombres y los Teléfonos son cadenas de
caracteres que pueden representarse con el tipo STRING.
1. Especifique, en MODULA-2, un TAD TablaContactos con operaciones constructoras,
selectoras/destructoras y predicados, que permita guardar una cantidad no conocida a priori de
Nombres y Télefonos. Además de las operaciones habituales de Tabla se necesita contar con
una operación llamada ListarTodosOrdenados que recibe una TablaContactos e imprime todos
los contactos en orden alfabético por Nombre, en forma de líneas que contienen cada una
Nombre y Télefono.
2. Implemente el TAD TablaContactos teniendo en cuenta que las operaciones de inserción
deben ejecutarse en orden log2(n) en caso promedio, siendo n la cantidad de elementos que
contiene la TablaContactos. Provea una representación para este TAD y el código de las
operaciones constructoras y de ListarTodosOrdenados. Omita el código del resto de las
operaciones del TAD. Se permite utilizar las operaciones <, >, = y <> para comparar STRINGs.
3. Considere que se quiere modificar el TAD TablaContactos, agregando la funcionalidad de
discado rápido que permita almacenar hasta K referencias a contactos. Esta funcionalidad se
implementa mediante las siguientes operaciones:
PROCEDURE InicializarLDRapido (VAR T: TablaContactos);
(* Inicializa el discado rápido en la TablaContactos T *)
PROCEDURE InsertarLDRapido (VAR T: TablaContactos; nomContacto: STRING; j:
STRING);
(* Inserta en la posición j<=K del discado rápido de T una referencia al
contacto ya existente en T con nombre=nomContacto *)
PROCEDURE BusquedaRapida (T: TablaContactos; j: CARDINAL);
(* Imprime el teléfono y nombre del contacto almacenado en la posición j<=K
discado rápido de T *)
del
Se pide:
a) Modifique la representación del TAD que propuso como solución a la parte 2 de forma
de permitir resolver la operación BusquedaRapida en O(1).
b) Implemente InicializarLDRapido, InsertarLDRapido y BusquedaRapida.
Solución ejercicio 1
Parte 1
PROCEDURE InsOrd (e : CARDINAL; l : ListaNat): ListaNat;
VAR res : ListaNat;
BEGIN
IF (l = NIL) OR (l^.elem > e) THEN
NEW (res);
res^.elem := e;
res^.sig := l
ELSE
res
:= l;
res^.sig := InsOrd(e,l^.sig)
END;
RETURN res
END InsOrd;
Parte 2
PROCEDURE GenerarRec (a : ABNat; VAR res : ListaNat);
BEGIN
IF a # NIL THEN
res := InsOrd(a^.nodo,res);
GenerarRec(a^.izq,res);
GenerarRec(a^.der,res)
END
END GenerarRec;
PROCEDURE GenerarListaOrd (a : ABNat): ListaNat;
VAR res : ListaNat;
BEGIN
res := NIL;
GenerarRec(a,res);
RETURN res
END GenerarListaOrd;
Parte 3
PROCEDURE OrdenarRec (a : ABNat; VAR l : ListaNat): ABNat;
VAR res : ABNat;
laux : ListaNat;
BEGIN
res := NIL;
IF a # NIL THEN
NEW (res);
res^.izq := OrdenarRec(a^.izq,l);
res^.nodo := l^.elem;
laux := l;
l
:= l^.sig;
DISPOSE(laux);
res^.der := OrdenarRec(a^.der,l)
END;
RETURN res
END OrdenarRec;
PROCEDURE Ordenar (a : ABNat): ABNat;
VAR l : ListaNat;
BEGIN
l := GenerarListaOrd(a);
RETURN OrdenarRec(a,l)
END Ordenar;
Solución ejercicio 2
Parte 1
PROCEDURE CreoTabla (): TablaContactos;
(* retorna la tabla vacía *)
PROCEDURE Insertar (d: STRING; r: STRING; VAR T: TablaContactos);
(* Define T(d) = r, independientemente de que T(d) estuviera ya definido *)
PROCEDURE EsVacia (T: TablaContactos): BOOLEAN
(* retorna TRUE sii T es vacía *)
PROCEDURE EstaDefinida (T: TablaContactos; d: STRING): BOOLEAN
(* retorna TRUE sii T está definida para d *)
PROCEDURE Recuperar(d: STRING; T: TablaContactos; VAR r: STRING);
(* retorna r si EstaDefinida(d)=TRUE y r = T(d) *)
PROCEDURE Borrar(d: STRING; VAR T: TablaContactos);
(* elimina la correspondencia que vincula a d en T. Luego de borrar,
EstaDefinida(T,d) es FALSE *)
PROCEDURE ListarTodosOrdenados (T: TablaContactos);
(* imprime todos los contactos en orden alfabético por Nombre, en forma de
líneas que contienen cada una: Nombre, Télefono. *)
Parte 2
La representación es un ABB, de este modo la operación Insertar tiene orden de ejecución
logarítmico en caso promedio.
TYPE TablaContactos = POINTER TO TCNodo;
TCNodo = RECORD
nom, tel: STRING;
izq, der: TablaContactos;
END;
PROCEDURE CreoTabla (): TablaContactos;
BEGIN
RETURN NIL;
END CreoTabla;
PROCEDURE Insertar (d: STRING; r: STRING; VAR T: TablaContactos);
(* Define T(d) = r, independientemente de que T(d) estuviera ya definido *)
BEGIN
IF (T=NIL) THEN
NEW(T);
T^.nom:=d;
T^.tel:=t;
T^.izq:=NIL;
T^.der:=NL;
ELSEIF (T^.nom=d) THEN
T^.tel:=t;
ELSEIF (T^.nom>d) THEN
Insertar (d, r, T^.izq);
ELSE
Insertar (d, r, T^.der);
END;
END Insertar;
PROCEDURE ListarTodosOrdenados (T: TablaContactos);
(* imprime todos los contactos en orden alfabético por Nombre, en forma de
líneas que contienen cada una: Nombre, Télefono. *)
BEGIN
IF (T<>NIL) THEN
ListarTodosOrdenados(T^.izq);
WriteString(T^.nom);
WriteString(' ;');
WriteString(T^.tel);
WriteLn;
ListarTodosOrdenados(T^.der);
END;
END ListarTodosOrdenados;
Parte 3
Se agrega al tipo un arreglo de largo K de punteros a nodos del árbol. De esta forma dada una
posición j con 1<=j<=k se puede obtener en O(1) los datos del registro en esa posición.
TYPE PTC= POINTER TO TCNodo;
TCNodo = RECORD
nom, tel: STRING;
izq, der: PTC;
END;
TablaContactos = RECORD
tablaC: PTC;
busRap : ARRAY[1..K] OF PTC;
END;
PROCEDURE InicializarLDRapido (VAR T: TablaContactos);
(* Pre: T es una TablaContactos y T(n). Pos: inserta una referencia a NIL para
todos los lugares de la lista de discado rápido independientemente de lo que
hubiera antes. *)
VAR j: PTC;
BEGIN
FOR j:=1 TO K DO
T^.busRap[j]:=NIL;
END;
END InicializarLDRapido;
PROCEDURE InsertarLDRapido (VAR T: TablaContactos; n: STRING; j: CARDINAL);
(* Pre: j<=K, T es una TablaContactos y T(n) esta definido en tc. Pos: inserta
una referencia a n y T(n) en el lugar j de la lista de discado rápido
independientemente de lo que hubiera antes. *)
VAR tc: PTC;
BEGIN
tc:= T^.tablaC;
WHILE (tc^.nom<>n) DO
IF (tc^.nom>n) THEN
tc:= tc^.der;
ELSE
tc:= tc^.izq;
END;
T^.busRap[j]:=tc;
END InsertarLDRapido;
PROCEDURE BusquedaRapida (T: TablaContactos; j: CARDINAL);
(* Pre: j<=K y T es una TablaContactos. Pos: imprime el Nombre y Télefono de
la persona ubicada en el lugar j de la lista de discado rápido o NIL en caso de
que j no esté definido en la lista de discado rápido. *)
BEGIN
WriteString(T^.busRap[j]^.nom);
WriteString(' ;');
WriteString(T^.busRap[j]^.tel);
WriteLn;
END BusquedaRapida;
Descargar