Solución Práctico 10 - Facultad de Ingeniería

Anuncio
Programación 2
Solución Práctico 10 - Diseño de Tipos Abstractos de Datos
Solución Práctico 10
Objetivos
Profundizar en diferentes especificaciones e implementaciones para TADs.
Practicar con versiones acotadas y no acotadas de los TADs, así como con estructuras estáticas y
dinámicas.
Practicar en diseñar TADs adecuados para resolver nuevos problemas, tomando en cuenta requerimientos como por ejemplo de eficiencia en tiempo o en espacio.
Ejercicio 2
(Examen Diciembre 2003)
Especifique un TAD T de elementos de un tipo genérico que permita almacenar a lo sumo K elementos donde se respeta la política LIFO (el último en entrar es el primero en salir). Se pide considerar
operaciones constructoras, selectoras/destructoras y predicados. La operación de inserción no debe
tener precondición, esto es: siempre se pueden agregar elementos pero sólo los últimos K (a lo sumo)
se consideran.
Desarrolle en una implementación del TAD T en la que las operaciones constructoras, selectoras y
predicados se realicen sin recorrer la estructura.
Solución Ejercicio 1
a) La Figura 1 presenta una especificación para el TAD T (Pila circular acotada).
# define K < valor apropiado >
/** * constructoras ** */
T vacia ();
/* construye una estructura ( pila ) vacia que puede almacenar hasta K elementos */
T insertar ( generico e , T p );
/* agrega el elemento e a la estructura */
/* si la estrucutura ya contiene K elementos , se elimina el mas viejo */
/** * selectoras ** */
generico tope ( T p );
/* devuelve el elemento que ha sido insertado en ultima instancia */
/* pre : ! esta_vacia ( p ) */
T quitar ( T p );
/* devuelve la estructura sin el elemento mas nuevo */
/* pre : ! esta_vacia ( p ) */
/** * predicados ** */
bool esta_vacia ( T p );
/* devuelve true sii la estructura esta vacia */
bool tiene_k ( T p );
/* devuelve true sii la estructura cuenta con K elementos */
Figura 1: Especificación para el TAD T.
b) A continuación una implementación estática para el TAD T.
Instituto de Computación - Facultad de Ingeniería - UdelaR
Página 1 de 6
Programación 2
Solución Práctico 10 - Diseño de Tipos Abstractos de Datos
struct nodoT {
generico vector [ K ];
int tope , base , cant ;
};
typedef nodoT * T ;
T vacia (){
T nuevaT = new
nuevaT - > base =
nuevaT - > tope =
nuevaT - > cant =
return nuevaT ;
};
nodoT ;
0;
K -1; /* Marca el ultimo en ser insertado */
0;
T insertar ( generico e , T p ){
p - > tope = (p - > tope + 1) % K ; /* Resto de la division entera o modulo */
p - > vector [p - > tope ] = e ;
if (p - > cant < K )
p - > cant ++;
else
p - > base = (p - > base + 1) % K ;
};
generico tope ( T p ){
return p - > vector [p - > tope ];
};
T quitar ( T p ){
p - > cant - -;
p - > tope - -;
if (p - > tope < 0)
p - > tope = K -1;
return p ; /* comparte memoria */
};
bool esta_vacia ( T p ){
return p - > cant == 0;
};
bool tiene_k ( T p ){
return p - > cant == K ;
};
Notar la relación que existe entre vacia, insertar y quitar y cómo se logra la circularidad en esta
implementación. En vacía se inicializa el tope a K-1 para que en la primera inserción el tope coincida con
la posición del último elemento insertado. La circularidad al insertar en parte se logra aplicando módulo
K cuando se incrementa el tope. En insertar la base (que es donde estaría el elemento más viejo) se mueve
si la pila se encuentra llena y en quitar se posiciona el tope al final del arreglo en caso de que queden
elementos.
No hay recorridas, por lo que todas las operaciones se ejecutan en tiempo constante peor caso.
Ejercicio 4
(Basado en: Examen Diciembre 2005)
Se quiere especificar e implementar un TAD Cola de Prioridad acotado (con un valor M) cuyos
elementos sean de tipo T y tengan identificadores enteros en el rango [1..M], que determinen a
cada elemento unívocamente. Cada elemento tiene asociada una prioridad: un número entero. Los
elementos son procesados según su prioridad, de mayor a menor.
Instituto de Computación - Facultad de Ingeniería - UdelaR
Página 2 de 6
Programación 2
Solución Práctico 10 - Diseño de Tipos Abstractos de Datos
Se debe especificar un TAD Cola de Prioridad (empty, isEmpty, insert, max, deleteMax, isFull) de
acuerdo a lo descrito arriba que incluya como funcionalidad adicional una operación que dado el
identificador x de un elemento y un número natural n, decremente el valor de prioridad del elemento
x en n unidades, si x está en la estructura.
También se debe proponer las estructuras y representaciones a usar en la implementación del TAD
anterior de tal manera que las operaciones insert, deleteMax y la operación adicional realicen log2 (n)
comparaciones en el peor caso, siendo n la cantidad de elementos en la cola de prioridad. Además,
max e isFull deben operar sin recorrer la cola de prioridad. Concretamente:
• Explique, con un dibujo y los comentarios pertinentes, la estructura que utilizaría para implementar el TAD, justificando cómo se satisfacen las restricciones previamente establecidas.
• Defina en C* la estructura utilizada para representar el TAD, pero NO implemente las operaciones del TAD.
Solución Ejercicio 2
Respecto a la especificación la Figura 2 presenta el TAD Cola de Prioridad (Cola de prioridad con
identificadores acotados en un rango).
/** * constructoras ** */
void empty ( CPrio & c );
/* Retorna la cola de prioridad vacia . */
void insert ( T dato , int id , int prio , CPrio & c );
/* Inserta el dato en la cola c con identificador id y prioridad prio .
/* Pre : ! isFull ( c ). */
/* Pre : No existe elemento con identificador id en c . */
/* Pre : id esta en el rango 1.. M */
*/
void decrPrio ( int id , int decr , CPrio & c );
/* Decrementa el valor de prioridad del elemento con identificador id en decr unidades .
/* Pre : Existe elemento con identificador id en c . */
/* Pre : id esta en el rango 1.. M */
/** * selectoras ** */
T max ( CPrio c );
/* retorna el elemento de mayor prioridad .
/* Pre : ! isEmpty ( c ). */
*/
*/
/** * predicados ** */
bool isEmpty ( CPrio c );
/* Devuelve true sii la estructura esta vacia */
bool isFull ( CPrio c );
/* devuelve true sii la estructura esta llena */
/** * destructoras ** */
void deleteMax ( CPrio & c );
/* Elimina el elemento de mayor prioridad . */
/* Pre : ! isEmpty ( c ). */
Respecto a la implementación se propone formar una estructura compleja, que consista de una tabla
y un heap vinculados a través de los identificadores y las posiciones para cumplir las restricciones de
orden. El heap se utiliza para manejar las prioridades y todas las operaciones de la cola, como es usual,
pero la exigencia de la operación adicional, nos obliga a tener una tabla vinculada al heap, para evitar la
búsqueda lineal y acceder en tiempo constante a cualquier elemento dado su identificador, para así poder
decrementarle la prioridad al hacer un filtrado en log2(n) peor caso.
Instituto de Computación - Facultad de Ingeniería - UdelaR
Página 3 de 6
Programación 2
Solución Práctico 10 - Diseño de Tipos Abstractos de Datos
Lo primero que hay que visualizar es el árbol(heap) y la tabla para un acceso en tiempo constante a
cualquier nodo:
Yendo a la implementación concreta en C y dado que la cantidad máxima de elementos está acotada
en M y que el rango de los identificadores es [1..M], las estructuras consideradas serán:
Heap: arreglo con tope (de 1 a M) que almacene elementos de tipo T con su prioridad e identificador.
Tabla: arreglo de 1 a M que almacene enteros de rango [0..M] que indican la posición en el Heap del
elemento que tiene como identificador el índice del arreglo, donde 0 (o vacío en el dibujo) indica la
no existencia de dicho elemento en la cola.
Por lo que la figura anterior se puede ver también como:
La operación max se soluciona obteniendo el primer elemento del heap, lo cual no requiere recorrer la
cola de prioridad.
La operación isFull se soluciona verificando que el tope del arreglo sea igual a M, lo cual tampoco
requiere recorrer la cola de prioridad.
Ya para la operación decrPrio obsérvese qué ocurre en caso de querer decrementar en 10 la prioridad
del nodo de identificador 1:
1) Se accede al nodo del heap sin recorrer ninguna estructura de la cola utilizando la tabla:
Instituto de Computación - Facultad de Ingeniería - UdelaR
Página 4 de 6
Programación 2
Solución Práctico 10 - Diseño de Tipos Abstractos de Datos
2) Se aplica el filtrado todas las veces que sea necesario (en este caso una vez, intercambiando 14 por
21). Notar que también se debe actualizar la tabla en cada intercambio del filtrado:
3) Así que finalmente queda:
Como un filtrado requiere log2(n) en peor caso en un heap, y la tabla se accede en tiempo constante,
se cumple con las restricciones del peor caso. Las operaciones insert y deleteMax se resuelven de forma
similar.
Finalmente la estructura en C sería:
Instituto de Computación - Facultad de Ingeniería - UdelaR
Página 5 de 6
Programación 2
Solución Práctico 10 - Diseño de Tipos Abstractos de Datos
# define M < valor apropiado >
struct nodo {
int id , prio ;
T dato ;
};
struct CPrio {
int tabla [ M ];
nodo heap [ M ];
int topeHeap ;
};
Instituto de Computación - Facultad de Ingeniería - UdelaR
Página 6 de 6
Descargar