Sei sulla pagina 1di 5

Estructuras de datos y algoritmos Solución del examen del 28 de enero de 2014

Ingeniería Informática Escuela de Ingeniería y Arquitectura, Universidad de Zaragoza

Solución del Ejercicio 1:


espec pizarras
usa asignaturas,alumnos,fechas,horas,cadenas,enteros,booleanos
{la asignatura incluye un código entero y el alumno un identificador entero}
género pizarra {Foro de mensajes y comentarios para alumnos matriculados en asignaturas}
operaciones
creaPizarra: -> pizarra
{Devuelve una pizarra vacía (sin asignaturas, alumnos, mensajes ni comentarios)}

añadeAsignatura: pizarra p , asignatura asig -> pizarra


{Dada la pizarra p y la asignatura asig:
(a) si no había en p ninguna asignatura con código igual al de asig, entonces devuelve
la pizarra resultante de añadir asig a p (sin mensajes);
(b) si ya había en p una asignatura con código igual al de asig, entonces devuelve
una pizarra igual a p}

asignatura?: pizarra p , entero códAsig -> booleano


{Devuelve verdad si y sólo si en p hay una asignatura con código igual a códAsig}

parcial buscaAsignatura: pizarra p , entero códAsig -> asignatura


{Dada la pizarra p y el código de asignatura códAsig devuelve la asignatura de p con
código códAsig. Parcial: no está definida si asignatura?(p,códAsig)=falso}

borraAsignatura: pizarra p , entero códAsig -> pizarra


{Dada la pizarra p y el código de asignatura códAsig:
(a) si asignatura?(p,códAsig)=verdad, entonces devuelve la pizarra resultante de
eliminar de p la asignatura con código códAsig (se eliminan sus mensajes y se
desmatriculan los alumnos);
(b) si asignatura?(p,códAsig)=falso, entonces devuelve una pizarra igual a p}

añadeAlumno: pizarra p , alumno alu -> pizarra


{Dada la pizarra p y el alumno alu:
(a) si no había en p ningún alumno con identificador igual al de alu, entonces
devuelve la pizarra resultante de añadir alu a p;
(c) si ya había en p un alumno con identificador igual al de alu, entonces devuelve
una pizarra igual a p }

alumno?: pizarra p , entero idAlu -> booleano


{Devuelve verdad si y sólo si en p hay un alumno con identificador igual a idAlu}

parcial buscaAlumno: pizarra p , entero idAlu -> alumno


{Dada la pizarra p y el identificador de alumno idAlu devuelve el alumno de p con
identificador idAlu. Parcial: no está definida si alumno?(p,idAlu)=falso}

borraAlumno: pizarra p , entero idAlu -> pizarra


{Dada la pizarra p y el identificador de alumno idAlu:
(a) si alumno?(p,idAlu)=verdad, entonces devuelve la pizarra resultante de eliminar de
p el alumno con identificador idAlu (no se eliminan sus mensajes);
(b) si alumno?(p,idAlu)=falso, entonces devuelve una pizarra igual a p }

parcial matricula: pizarra p , entero codAsig , entero idAlu -> pizarra


{Dada la pizarra p, el código códAsig de una asignatura de p y el identificador
idAlu de un alumno de p:
(a) si no estaba matriculado ese alumno en esa asignatura, entonces devuelve la
pizarra resultante, a partir de p, de matricular a ese alumno en esa asignatura;
(b) si ya estaba matriculado, entonces devuelve una pizarra igual a p.
Parcial: no está definida si asignatura?(p,códAsig)=falso o alumno?(p,idAlu)=falso}

parcial estáMatriculado: pizarra p , entero codAsig , entero idAlu -> booleano


{Dada la pizarra p, el código códAsig de una asignatura de p y el identificador
idAlu de un alumno de p, devuelve verdad si y sólo si el alumno de identificador idAlu
está matriculado en la asignatura de código códAsig.
Parcial: no está definida si asignatura?(p,códAsig)=falso o alumno?(p,idAlu)=falso}
parcial desmatricula: pizarra p , entero idAlu , entero codAsig -> pizarra
{Dada la pizarra p, el código códAsig de una asignatura de p y el identificador
idAlu de un alumno de p:
(a) si estaba matriculado ese alumno en esa asignatura, devuelve la pizarra
resultante, a partir de p, de desmatricular a ese alumno de esa asignatura;
(b) si no estaba matriculado, entonces devuelve una pizarra igual a p.
Parcial: no está definida si asignatura?(p,códAsig)=falso o alumno?(p,idAlu)=falso}

parcial añadeMensaje: pizarra p , entero codAsig , entero idAlu ,


fecha f , hora h , cadena t -> pizarra
{Devuelve la pizarra resultante de añadir en p un nuevo mensaje (sin comentarios) del
alumno idAlu a la asignatura codAsig con fecha f, hora h y texto t.
Parcial: no está definida si asignatura?(p,códAsig)=falso o alumno?(p,idAlu)=falso o
estáMatriculado(p,códAsig,idAlu)=falso o el instante (f,h) no es posterior al del
último mensaje existente en p para la asignatura codAsig}

parcial añadeComentario: pizarra p , entero codAsig , entero idAlu ,


fecha fechaMen , hora horaMen ,
fecha fechaCom , hora horaCom , cadena t -> pizarra
{Devuelve la pizarra resultante de añadir en p un nuevo comentario del alumno idAlu con
fecha fechaCom, hora horaCom y texto t, al mensaje de fecha fechaMen y hora horaMen de
la asignatura codAsig. Parcial: no está definida si asignatura?(p,códAsig)=falso o
alumno?(p,idAlu)=falso o estáMatriculado(p,códAsig,idAlu)=falso o no existe en la
lista de mensajes de esa asignatura un mensaje con fecha fechaMen y hora horaMen, o el
instante (fechaCom,horaCom) no es posterior al del último comentario existente en p
para el mensaje de fecha fechaMen y hora horaMen de la asignatura codAsig}
fespec

Solución del Ejercicio 2:


Diccionario (árbol AVL) de alumnos Diccionario (tabla
(clave de búsqueda=identificador) hash) de asignaturas
(clave=código) En particular, cada asignatura
incluye una lista de mensajes

.
.
. y cada mensaje incluye
una lista de comentarios

En particular, cada alumno


incluye una lista de códigos
de asignaturas en las que
está matriculado

Podemos almacenar una pizarra en un par formado por un árbol de búsqueda binario equilibrado (AVL) de
alumnos, usando el identificador del alumno como clave de búsqueda, y una tabla hash de asignaturas, usando
el código de asignatura como clave de búsqueda. Cada nodo de alumno del árbol incluirá, en particular, una
lista de códigos de asignaturas en las que está matriculado el alumno. Cada asignatura incluirá, en particular,
una lista de mensajes (ordenada por fecha-hora y apuntada al primero y al último de la lista). Cada mensaje de
cada lista incluirá, en particular, una lista de comentarios (ordenada por fecha-hora y apuntada al primero y al
último).

{fecha y hora}
tipos
fecha = registro
día,mes,año:entero
freg
hora = registro
hora,minuto,segundo:entero
freg
{comentario y lista de comentarios con puntero al 1º y al último}
tipos
comentario = registro
fechaComen:fecha;
horaComen:hora;
autorComen:entero; {identificador del autor}
textoComen:cadena;
freg
puntNodoComentario = nodoComentario
nodoComentario = registro
dato:comentario;
sig:puntNodoComentario
freg
listaComentarios = registro
primero,último:puntNodoComentario
freg

{mensaje y lista de mensajes con puntero al 1º y al último}


tipos
mensaje = registro
fechaMen:fecha;
horaMen:hora;
autorMen:entero; {identificador del autor}
textoMen:cadena;
comentariosMen:listacomentarios
freg
puntNodoMensaje = nodoMensaje
nodoMensaje = registro
dato:mensaje;
sig:puntNodoMensaje
freg
listaMensajes = registro
primero,último:puntNodoMensaje
freg

{asignatura y tabla hash de asignaturas (dispersión cerrada, por ejemplo)}


constante maxAsig = 97 {por ejemplo}
tipos
asignatura = registro
código:entero;
nombre:cadena;
mensajes:listaMensajes
freg
tpEstado=(libre,ocupado,borrado)
nodoTablaAsig = registro
asig:asignatura;
estado:tpEstado
freg
tablaAsignaturas = vector[0..maxAsig-1] de nodoTablaAsig

{alumno, lista de asignaturas en que está matriculado (ordenada por códigos


de asignatura crecientes), y árbol AVL de alumnos ordenados por identificador}
tipos
listaAsignaturas = nodoListaAsignaturas
nodoListaAsignaturas = registro
código:entero;
sig:listaAsignaturas
freg
alumno = registro
identificador:entero;
nombre,apellido1,apellido2:cadena;
matrículadas:listaAsignaturas
freg
factorEquil = (pesadoIzq,equilibrado,pesadoDer)
AVLalumnos = nodoAlumno
nodoAlumno = registro
dato:alumno;
equilíbrio;factorEquil;
izq,der:AVLalumnos
freg
{pizarra}
tipo
pizarra = registro
asignaturas:tablaAsignaturas;
alumnos:AVLalumnos
freg

Solución del Ejercicio 3:

A continuación se presentan como ejemplo dos alternativas de implementación que se diferencian en el cálculo y
detección del cumplimiento de la condición requerida sobre los productos de los nodos de los caminos.

Alternativa A:

función test(a:arbin; K:entero; P:entero) devuelve booleano


{enunciado}
tipo tabla:vector[0..K] de entero
variables sumas:tabla; i:entero; respuesta:booleano; resultado:entero
principio
para i:=0 hasta K hacer
sumas[i]:=0
fpara;
testRec(a,resultado,respuesta,0,sumas);
respuesta:=respuesta and (resultado=P);
para i:=0 hasta K hacer
escribirLínea(“Nivel ”, i, “: ”, sumas[i])
fpara;
devuelve respuesta
fin

procedimiento testRec(ent a:arbin; sal producto:entero; sal respuesta:booleano;


ent nivel:entero; e/s T:tabla)
{Es una inmersión de la función test en la que:
(1) a es la raíz de un subárbol del árbol original y no vacío;
(2) hay que comprobar si en todos los caminos desde a hasta sus hojas el producto de los
valores de los nodos encontrados en el camino produce el mismo resultado en todos los
caminos, y devolver la respuesta en el booleano respuesta y el valor obtenido en el
entero producto;
(3) nivel es el nivel de a dentro del árbol original;
(4) en cada T[i] se acumula la suma de los elementos de nivel i del árbol original.}

variables respIzq,respDer:booleano; productoI,productoD:entero;


principio
T[nivel]:=T[nivel]+a.dato;
selección
a.izq=nil and a.der=nil: respuesta:=true;
producto:=a.dato;
a.izqnil and a.der=nil: testRec(a.izq, productoI, respuesta, nivel+1, T);
producto:=productoI*a.dato;
a.izq=nil and a.dernil: testRec(a.der, productoD, respuesta, nivel+1, T);
producto:=productoD*a.dato;
a.izqnil and a.dernil: testRec(a.izq, productoI, respIzq, nivel+1, T);
testRec(a.der, productoD, respDer, nivel+1, T);
respuesta:=respIzq and respDer and (productoI=productoD);
producto:=productoI*a.dato
fselección
fin

Alternativa B:

función test(a:arbin; K:entero; P:entero) devuelve booleano


{enunciado}
tipo tabla:vector[0..K] de entero
variables sumas:tabla; i:entero; respuesta:booleano
principio
para i:=0 hasta K hacer
sumas[i]:=0
fpara;
testRec(a,P,1,respuesta,0,sumas);
para i:=0 hasta K hacer
escribirLínea(“Nivel ”, i, “: ”, sumas[i])
fpara;
devuelve respuesta
fin

procedimiento testRec(ent a:arbin; ent prodObj:entero; ent prodAcu:entero;


sal respuesta:booleano; ent nivel:entero; e/s T:tabla)
{Es una inmersión de la función test en la que:
(1) a es la raíz de un subárbol del árbol original y no vacío;
(2) hay que comprobar si en todos los caminos desde la raíz del árbol original hasta sus
hojas el producto de los valores de los nodos encontrados en el camino produce el mismo
resultado en todos los caminos y con resultado igual a prodObj, y devolver la respuesta
en el booleano respuesta;
(3) prodAcu es el producto acumulado de los nodos encontrados en el camino ya recorrido
para llegar desde la raíz del árbol original hasta la raíz del árbol a (que es un
subárbol del árbol original);
(4) nivel es el nivel de a dentro del árbol original;
(5) en cada T[i] se acumula la suma de los elementos de nivel i del árbol original.}

variables respIzq,respDer:booleano;
principio
T[nivel]:=T[nivel]+a.dato;
prodAcu:=prodAcu*a.dato;
selección
a.izq=nil and a.der=nil: respuesta:=(prodObj=prodAcu);
a.izqnil and a.der=nil: testRec(a.izq, prodObj, prodAcu, respuesta, nivel+1, T);
a.izq=nil and a.dernil: testRec(a.der, prodObj, prodAcu, respuesta, nivel+1, T);
a.izqnil and a.dernil: testRec(a.izq, prodObj, prodAcu, respIzq, nivel+1, T);
testRec(a.der, prodObj, prodAcu, respDer, nivel+1, T);
respuesta:=respIzq and respDer
fselección
fin

Costes en ambas alternativas:

El procedimiento testRec realiza un recorrido del árbol (recursivo), es decir cada nodo del árbol se visita sólo una vez, y
todas las operaciones que se realizan para cada nodo del árbol son simples, de coste O(1), por tanto el coste de testRec es
O(N) siendo N el número de nodos del árbol.

El coste de la función test será el coste de su llamada a testRec, más el coste de inicializar la tabla para las sumas de
los niveles, más el coste de escribir en pantalla los resultados calculados en la tabla, en ambos casos el coste es lineal en el
tamaño de la tabla O(K). Si el valor de K dado es una buena cota para la altura del árbol (puede ser mayor que la altura
del árbol pero al menos no es mucho mayor que N), al simplificar podemos asumir que K es aproximadamente la altura
del árbol, y sabemos que la altura del árbol binario es en el mejor de los casos log2N (árbol completo) o N–1 (árbol
degenerado). Por lo tanto, el coste asintótico de la función test es O(N).

Potrebbero piacerti anche