Solución Parcial de Programación 2

Anuncio
Instituto de Computación. Facultad de Ingeniería. Universidad de la República
Solución Parcial de Programación 2
9 de Julio 2004
Ejercicio 1 – Parte a:
Para resolver el ejercicio se utiliza el TAD Cola de Naturales, el mismo está definido por las siguientes
operaciones:
TYPE Queue;
(* Procedimiento creador de una cola vacía *)
PROCEDURE Create(VAR q : Queue);
(* Procedimiento encargado de encolar el elemento t en la cola q *)
PROCEDURE Enqueue(t : ARBOL; VAR q : Queue);
(* Función que retorna TRUE sii la cola q es vacía *)
PROCEDURE Empty(q : Queue):BOOLEAN;
(* Función que elimina el primer elemento de la cola q.*)
(* Pre: NOT Empty(q); *)
PROCEDURE Dequeue(VAR q : Queue);
(* Función que retorna el primer elemento de la cola q.*)
(* Pre: NOT Empty(q); *)
PROCEDURE Front(q : Queue): ARBOL;
La solución del problema se presenta a continuación:
PROCEDURE Print(t : ARBOL);
VAR
q : Queue;
current : ARBOL;
BEGIN
IF (t <> NIL) THEN
Create(q);
Enqueue(t, q);
WHILE (NOT Empty(q)) DO
current := Front(q);
Dequeue(q);
REPEAT
IF (current^.PrimerHijo <> NIL) DO
Enqueue(current^.PrimerHijo);
END;
WriteCard(current^.Dato);
current := current^.SigHermano;
UNTIL (current = NIL)
END
END
END Print;
Ejercicio 1 – Parte b:
Para la solución del ejercicio se utiliza el siguiente procedimiento auxiliar que libera la memoria de la
estructura del árbol:
(* Procedimiento que elimina la estructura del árbol t *)
PROCEDURE Delete(VAR t : ARBOL);
BEGIN
IF (t <> NIL) THEN
Delete(t^.PrimerHijo);
Delete(t^.SigHermano);
DISPOSE(t);
END;
END Delete;
La solución del ejercicio se presenta a continuación:
(* Procedimiento que elimina el subárbol correspondiente al nodo dato *)
PROCEDURE DeleteSubTree(VAR t : ARBOL, x : CARDINAL);
VAR current : ARBOL;
BEGIN
IF (t <> NIL) THEN
IF (t^.Dato = x) THEN
current := t;
t := t^.SigHermano;
current^.SigHermano := NIL;
Delete(current);
(* Una alternativa a las dos lineas anteriores es:
Delete(current^.PrimerHijo);
DISPOSE(current); *)
ELSE
DeleteSubTree(t^.PrimerHijo, x);
DeleteSubTree(t^.SigHermano, x);
END;
END;
END DeleteSubTree;
Ejercicio 2 – Parte a:
Se presenta una solución dinámica implementada a partir de la utilización de una lista doblemente enlazada
con punteros al comienzo y al final. Otra opción hubiera sido realizar una solución estática implementada a
partir de la utilización de un arreglo circular, indicando en la estructura el primer elemento o el último
elemento y la cantidad.
IMPLEMENTATION MODULE Historia;
TYPE
Lista
= POINTER TO Nodo;
Nodo
= RECORD
sig, ant : Lista;
elem
: INTEGER;
END;
Historia = POINTER TO Cabezal;
Cabezal = RECORD
prim, ult : Lista;
cant
: INTEGER;
END;
(* Devuelve una historia vacía *)
PROCEDURE CrearHistoria () : Historia;
VAR hist : Historia
BEGIN
NEW(hist);
hist^.ult
:= NIL;
hist^.prim
:= NIL;
hist^.cant := 0;
RETURN hist;
END CrearHistoria;
(* Inserta en la historia 'hist' el entero 'val'.
En caso de que EstaLlenaHistoria(hist) sea TRUE se elimina el elemento más antiguo *)
PROCEDURE InsertarHistoria ( val : INTEGER; VAR hist : Historia );
VAR nuevo, aborrar : Lista;
BEGIN
NEW(nuevo);
nuevo^.ant := NIL;
nuevo^.elem := val;
IF (EstaVaciaHistoria(hist)) THEN
nuevo^.sig := NIL;
(* el resto de la lista es vacía *)
hist^.ult
:= nuevo;
(* es el único elemento, por lo que es el último *)
hist^.cant := 1;
ELSE
IF (EstaLlenaHistoria(hist)) THEN
(* hay que quitar el elemento más antiguo *)
aborrar := hist^.ult;
(* apunto con un auxiliar para luego liberar *)
hist^.ult^.ant^.sig := NIL; (* el puntero al siguiente del anteúltimo *)
hist^.ult := hist^.ult^.ant; (* debe pasar a ser el último *)
DISPOSE(aborrar)
(* se libera la memoria del que era último *)
ELSE
hist^.cant := hist^.cant + 1 (* en caso de que no estuviera lleno se agrega 1 *)
END;
nuevo^.sig := hist^.prim;
(* se pone como siguiente al nuevo la lista anterior *)
hist^.prim^.ant := nuevo;
END;
hist^.prim := nuevo
(* ahora el cabezal tiene como comienzo el nuevo nodo *)
END InsertarHistoria;
(* Devuelve TRUE únicamente si la historia 'hist' no tiene elementos *)
PROCEDURE EstaVaciaHistoria ( hist : Historia ) : BOOLEAN;
BEGIN
RETURN ( hist^.cant = 0 )
END EstaVaciaHistoria;
(* Devuelve TRUE únicamente si la historia 'hist' tiene MAXHIST elementos *)
PROCEDURE EstaLlenaHistoria ( hist : Historia ) : BOOLEAN;
BEGIN
RETURN ( hist^.cant = MAXHIST )
END EstaLlenaHistoria;
(* Devuelve el último elemento ingresado en la historia 'hist'.
Precondicion: NOT EstaVaciaHistoria(hist) *)
PROCEDURE ObtenerTopeHistoria ( hist : Historia ) : INTEGER;
BEGIN
RETURN ( hist^.prim^.elem )
END ObtenerTopeHistoria;
(* Elimina el elemento más reciente de la historia 'hist'.
Precondicion: NOT EstaVaciaHistoria (hist). *)
PROCEDURE QuitarTopeHistoria ( VAR hist : Historia );
VAR
aborrar : Lista;
BEGIN
aborrar := hist^.prim;
hist^.prim := hist^.prim^.sig;
hist^.cant := hist^.cant - 1;
IF (hist^.cant = 0) THEN
(* queda vacio => hay que dejarlo tal como CrearHistoria *)
hist^.ult := NIL
ELSE
hist^.prim^.ant := NIL
END;
DISPOSE(aborrar);
END QuitarTopeHistoria;
(* Libera toda la memoria reservada por la historia 'hist' *)
PROCEDURE DestruirHistoria ( VAR hist : Historia );
BEGIN
WHILE (NOT EstaVaciaHistoria(hist)) DO
QuitarTopeHistoria(hist)
END
DISPOSE(hist);
END DestruirHistoria;
END Historia.
Ejercicio 2 – Parte b:
MODULE Maquina;
CONST
MAX = 100;
MALCOMANDO = 0;
ADICION = 1;
SUSTRACCION = 2;
DESHACER = 3;
REHACER = 4;
DESPLEGAR = 5;
SALIR = 6;
(* Procedimiento auxiliar que vacía una historia. *)
PROCEDURE VaciarHistoria ( VAR hist : Historia );
BEGIN
IF (NOT EstaVaciaHistoria(hist)) THEN
DestruirHistoria(hist);
hist := CrearHistoria()
END
END VaciarHistoria;
(* Procedimiento auxiliar que despliega un mensaje de error. *)
PROCEDURE DesplegarError ( mensaje : ARRAY OF CHAR );
BEGIN
WriteString("ERROR: ");
WriteString(mensaje);
WriteLn
END DesplegarError;
(* Procedimiento auxiliar que despliega un valor del tipo integer. *)
PROCEDURE Desplegar ( valor : INTEGER );
BEGIN
WriteInt(valor,0);
WriteLn
END Desplegar;
(* Procedimiento auxiliar que devuelve un valor del tipo cardinal a partir del comando ingresado. *)
PROCEDURE Cualcomando(comando : ARRAY OF CHAR): CARDINAL;
BEGIN
IF (CompareStr(comando,"adicion") = 0) THEN
RETURN ADICION
ELSIF (CompareStr(comando,"sustraccion") = 0) THEN
RETURN SUSTRACCION
ELSIF (CompareStr(comando,"deshacer") = 0) THEN
RETURN DESHACER
ELSIF (CompareStr(comando,"rehacer") = 0) THEN
RETURN REHACER
ELSIF (CompareStr(comando,"desplegar") = 0) THEN
RETURN DESPLEGAR
ELSIF (CompareStr(comando,"salir") = 0) THEN
RETURN SALIR
ELSE RETURN MALCOMANDO
END Cualcomando;
(**** Programa Principal ****)
VAR
opcion : CARDINAL;
x, valor : INTEGER;
comando : ARRAY [0..20] OF CHAR;
D, R : Historia;
exito : BOOLEAN;
BEGIN
x := 0;
D := CrearHistoria();
R := CrearHistoria();
Write('>');
Leer_Comando(comando,valor);
opcion := Cualcomando(comando);
WHILE (opcion # SALIR) DO
CASE opcion OF
ADICION: IF (ABS(x + valor) <= MAX) THEN
InsertarHistoria(x,D);
x := x + valor;
VaciarHistoria(R)
ELSE
DesplegarError("Excede el intervalo")
END |
SUSTRACCION: IF (ABS(x - valor) <= MAX) THEN
InsertarHistoria(x,D);
x := x - valor;
VaciarHistoria(R)
ELSE
DesplegarError("Excede el intervalo")
END |
DESHACER: IF (NOT EstaVaciaHistoria(D)) THEN
InsertarHistoria(x,R);
x := ObtenerTopeHistoria(D);
QuitarTopeHistoria(D)
ELSE
DesplegarError("Historia Vacia")
END |
REHACER: IF (NOT EstaVaciaHistoria(R)) THEN
InsertarHistoria(x,D);
x := ObtenerTopeHistoria(R);
QuitarTopeHistoria(R)
ELSE
DesplegarError("Historia Vacia")
END |
DESPLEGAR : Desplegar(x)
END;
Write('>');
Leer_Comando(comando,valor);
opcion := Cualcomando(comando);
END
END Maquina.
Descargar