Estructuras de datos II - Unidad de Programación

Anuncio
Estructuras de datos II.
Convocatoria: Junio 2005
1
Estructuras de datos II
Convocatoria: Junio 2005
Dpto. LSIIS. Unidad de Programación
Normas
Duración: El examen se compone de 1 ejercicio y una colección de preguntas cortas. Su duración será de dos horas
y cuarto. Transcurrida una hora del comienzo del examen se recogerán las preguntas cortas.
Calificaciones: Las calificaciones se publicarán en el tablón de anuncios de la asignatura el dı́a 20 de Junio de
2005.
Revisión: La revisión del examen se realizará el dı́a 22 de Junio de 2005.
Soluciones: Las soluciones a los ejercicios se publicarán en el tablón de la asignatura junto con las notas.
1.
Montı́culos sobre Ficheros Directos
[4 puntos]
La implementación de colas con prioridad vista en clase utiliza un montı́culo. Como es sabido, los montı́culos se pueden representar de forma eficiente utilizando una secuencia de elementos, puesto que se puede determinar de manera sencilla y eficiente el ı́ndice de la secuencia donde se encuentra el nodo padre y los hijos
de cualquier dado. En la implementación vista en clase, el montı́culo se implementa mediante un registro que
contiene un array Secuencia donde se guardan los pares (Elemento, P rioridad) y el contador Longitud.
En este ejercicio se pretende modificar la implementación de colas con prioridad basada en montı́culos de
manera que la estructura de datos Secuencia, en vez de un array, sea un fichero de acceso directo, mediante
la utilización del paquete Ada.Direct IO. Por tanto, los accesos a array de la implementación original se
deberán reemplazar por operaciones de lectura y escritura a fichero.
Se incluye a continuación la parte relevante de interfaz del paquete genérico colas con prioridad que
debemos utilizar.
with Ada . D i r e c t I O ;
generic
type T i p o E l e m e n t o i s private ;
package C o l a s P e r s i s
type ColaP i s limited private ;
subtype T i p o P r i o r i d a d i s N a t u r a l ;
procedure C r e a r V a c i a ( C o l a : out ColaP ) ;
function E s V a c i a ( C o l a : in ColaP ) return B o o l e a n ;
function E s t a L l e n a ( C o l a : in ColaP ) return B o o l e a n ;
procedure I n s e r t a r ( C o l a
: in out ColaP ;
E l e m e n t o : in T i p o E l e m e n t o ; P r i o r i d a d : in T i p o P r i o r i d a d ) ;
private
type Tipo Componente i s record
Elemento : Tipo Elemento ; P r i o r i d a d : T i p o P r i o r i d a d ;
end record ;
package S e c u e n c i a s i s new Ada . D i r e c t I O ( Tipo Componente ) ;
use S e c u e n c i a s ;
subtype T i p o P o s i c i o n i s P o s i t i v e C o u n t ;
subtype T i p o L o n g i t u d i s Count ;
type ColaP i s record
Secuencia : File Type ; Longitud : Tipo Longitud := 0;
end record ;
end C o l a s P e r s ;
Con esta implementación el código de la operación Crear Vacı́a es el siguiente:
procedure C r e a r V a c i a ( C o l a : out ColaP )
is
begin
Create ( Cola . Secuencia , I n O u t F i l e , ”” ) ;
Cola . Longitud : = 0 ;
end C r e a r V a c i a ;
Estructuras de datos II.
Convocatoria: Junio 2005
2
Se pide:
Apartado a) ¿Qué implementación es más eficiente en tiempo, la vista en clase que utiliza arrays, o la
propuesta en este ejercicio que utiliza memoria secundaria? ¿Por qué?
Apartado b) Indı́quense (varias) ventajas de la implementación propuesta respecto de la vista en clase.
¿Por qué?
Apartado c) Realı́cese el código de las operaciones Es Vacı́a, Está Llena e Insertar. Como recordatorio,
se incluye a continuación la parte relevante del paquete Ada.Direct IO.
generic
type E l e m e n t T y p e i s private ;
package Ada . D i r e c t I O i s
type F i l e T y p e i s limited private ;
type F i l e M o d e i s ( I n F i l e , I n o u t F i l e , O u t F i l e ) ;
type Count i s range 0 . . System . D i r e c t I O . Count ’ L a s t ;
subtype P o s i t i v e C o u n t i s Count range 1 . . Count ’ L a s t ;
procedure C r e a t e ( F i l e : in out F i l e T y p e ; Mode : in F i l e M o d e : = I n o u t F i l e ;
Name : in S t r i n g : = ” ” ; Form : in S t r i n g : = ” ” ) ;
procedure Open ( F i l e : in out F i l e T y p e ; Mode : in F i l e M o d e ;
Name : in S t r i n g ; Form : in S t r i n g : = ” ” ) ;
procedure C l o s e ( F i l e : in out F i l e T y p e ) ;
procedure D e l e t e ( F i l e : in out F i l e T y p e ) ;
procedure R e s e t ( F i l e : in out F i l e T y p e ; Mode : in F i l e M o d e ) ;
procedure Read ( F i l e : in F i l e T y p e ; I t e m : out E l e m e n t T y p e ;
From : in P o s i t i v e C o u n t ) ;
procedure Read ( F i l e : in F i l e T y p e ; I t e m : out E l e m e n t T y p e ) ;
procedure W r i t e ( F i l e : in F i l e T y p e ; I t e m : in E l e m e n t T y p e ;
To
: in P o s i t i v e C o u n t ) ;
procedure W r i t e ( F i l e : in F i l e T y p e ; I t e m : in E l e m e n t T y p e ) ;
procedure S e t I n d e x ( F i l e : in F i l e T y p e ; To : in P o s i t i v e C o u n t ) ;
function I n d e x ( F i l e : in F i l e T y p e ) return P o s i t i v e C o u n t ;
function S i z e ( F i l e : in F i l e T y p e ) return Count ;
function E n d O f F i l e ( F i l e : in F i l e T y p e ) return B o o l e a n ;
Solución
Apartado a)
El orden de complejidad para las distintas operaciones es idéntico en las dos implementaciones, la vista
en clase y la propuesta en este ejercicio. La diferencia radica en que en la implementación vista en clase
los accesos al montı́culo se realizan sobre un array que reside en memoria principal, mientras que en la
implementación propuesta en este ejercicio el montı́culo se almacena en memoria secundaria.
En el caso de la operación Insertar, en ambas implementaciones el orden de complejidad es logarı́tmico
(O(log n)), siendo n el número de elementos que contiene el montı́culo. Dado que en general los accesos a
memoria secundaria son más lentos que los accesos a memoria principal, la implementación vista en clase
será mas eficiente en tiempo que la implementación propuesta en este ejercicio.
Apartado b)
La implementación propuesta en este ejercicio presenta varias ventajas con respecto a la utilización de
arrays en memoria principal. Las dos ventajas fundamentales son:
1.
Los ficheros de acceso directo son estructuras de datos dinámicas en el sentido de que su tamaño puede
aumentar en tiempo de ejecución según sea necesario. De esta manera, no se necesita fijar un tamaño
máximo predeterminado para la cola con prioridad, como ocurre en la implementación que utiliza
arrays.
2.
En general, los ficheros de acceso directo pueden contener muchos más datos que los arrays almacenados
en memoria principal, porque la memoria secundaria suele tener mayor capacidad que la memoria
principal.
Estructuras de datos II.
Convocatoria: Junio 2005
3
En nuestro caso, la persistencia asociada al uso de ficheros no representa una ventaja importante, puesto
que se utilizan ficheros auxiliares temporales. Esto se puede observar en el código de la operación Crear Vacı́a
donde aparece la lı́nea:
Create ( Cola . Secuencia , I n O u t F i l e , ”” ) ;
donde se puede ver que el tercer argumento (nombre del fichero) es la cadena vacı́a. Los ficheros temporales
desaparecen cuando termina la ejecución del programa y como no tienen un nombre significativo, no se puede
acceder a ellos desde otros programas. Ni siquiera desde otra ejecución sucesiva del mismo programa.
Apartado c)
Es Vacı́a Para comprobar si una cola con prioridad es vacı́a basta con comprobar si su longitud es cero.
function E s V a c i a
( C o l a : ColaP )
return B o o l e a n i s
begin
return C o l a . L o n g i t u d = 0 ;
end E s V a c i a ;
Está Llena Como los ficheros directos son una estructura de datos dinámica, en principio pueden crecer
todo lo que sea necesario para guardar nuevos datos. Ası́ que una solución que se admite como válida es la
siguiente.
function E s t a L l e n a
( C o l a : ColaP )
return B o o l e a n
is
begin
return F a l s e ;
end E s t a L l e n a ;
Por otro lado, como la implementación de los ficheros binarios de acceso directo necesita internamente
un ı́ndice (cursor) que es de tipo Count, en la práctica el tamaño de los ficheros directos está limitado por el
valor máximo que podamos representar usando el tipo Count. Ası́ que otra implementación de la operación
Está Llena que es totalmente válida es la siguiente:
function E s t a L l e n a
( C o l a : ColaP )
return B o o l e a n
is
begin
return C o l a . L o n g i t u d = Count ’ L a s t ;
end E s t a L l e n a ;
Insertar Para la realización del procedimiento Insertar, como se dijo durante el examen, se podı́a asumir
la existencia del procedimiento auxiliar Intercambiar sin necesidad de implementarlo. Una posible implementación de dicho procedimiento es la mostrada a continuación:
procedure I n t e r c a m b i a r
( Secuencia
: in out F i l e T y p e ;
Pos1 , Pos2 : in
Tipo Posicion )
is
Componente1 , Componente2 : Tipo Componente ;
begin
Read ( S e c u e n c i a , Componente1 , Pos1 ) ;
Read ( S e c u e n c i a , Componente2 , Pos2 ) ;
W r i t e ( S e c u e n c i a , Componente2 , Pos1 ) ;
W r i t e ( S e c u e n c i a , Componente1 , Pos2 ) ;
end I n t e r c a m b i a r ;
Estructuras de datos II.
Convocatoria: Junio 2005
4
Finalmente se muestra una implementación del procedimiento Insertar. Este procedimiento empieza
incrementando la longitud de la secuencia y almacena el nuevo dato en la última posición de la secuencia.
Posteriormente intercambia los valores del dato actual (o problema) con el de su padre en el montı́culo hasta
que alcanzamos la raı́z del montı́culo o el dato actual está ordenado (su prioridad no es mayor que la del
padre).
procedure I n s e r t a r
( Cola
: in out ColaP ;
E l e m e n t o : in
Tipo Elemento ;
P r i o r i d a d : in
Tipo Prioridad )
is
Indice Actual , Indice Padre : Tipo Longitud ;
Padre : Tipo Componente ;
Ordenado : B o o l e a n : = F a l s e ;
begin
Cola . Longitud := Cola . Longitud + 1;
W r i t e ( C o l a . S e c u e n c i a , ( Elemento , P r i o r i d a d ) , C o l a . L o n g i t u d ) ;
I n d i c e A c t u a l := Cola . Longitud ;
while ( I n d i c e A c t u a l > 1 ) and not Ordenado loop
Indice Padre := Indice Actual / 2 ;
Read ( C o l a . S e c u e n c i a , Padre , I n d i c e P a d r e ) ;
i f ( P r i o r i d a d > Padre . P r i o r i d a d ) then
I n t e r c a m b i a r ( Cola . Secuencia , I n d i c e A c t u a l , I n d i c e P a d r e ) ;
Indice Actual := Indice Padre ;
else
Ordenado : = True ;
end i f ;
end loop ;
end I n s e r t a r ;
Observaciones
Algunas observaciones adicionales sobre la solución del ejercicio son las siguientes:
Para conocer la longitud de la secuencia en un momento dado se debe consultar el valor de Cola.Secuencia
y no el de Size (Cola.Secuencia) porque pueden no ser iguales. En concreto, las operaciones de borrado decrementan Cola.Secuencia, pero no Size (Cola.Secuencia).
La operación Insertar recibe un fichero que ya está abierto. El fichero se abre en la operación
Crear Vacı́a y se cierra en la operación Destruir. No se debe por tanto abrir ni cerrar durante
la ejecución de Insertar.
En la operación de Insertar hay que tener cuidado para no leer del fichero posiciones (padres) no
existentes, bien porque el nuevo elemento insertado sea el único de la cola (y por tanto no tiene padre),
bien porque el nodo problema es ya la raı́z del montı́culo tras iterar en el bucle que reconstruye la
propiedad de los valores de un montı́culo.
Convocatoria: Junio 2005
Estructuras de datos II.
2.
5
Preguntas cortas
[6 puntos]
Apellidos: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Nombre: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Número de matrı́cula: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Grupo: . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Esta hoja se deberá rellenar con los datos del alumno y entregar como parte del examen. Todas
las preguntas valen 1 punto. La primera de ellas es una pregunta de test, y sólo tiene una respuesta válida. Si
se responde de manera incorrecta, se descontará medio punto de la nota. El resto de preguntas no descuentan
puntuación si se responden incorrectamente. Este ejercicio se recogerá transcurrida 1 hora desde el comienzo
del examen.
1.
Las bases de datos surgen para paliar los problemas de las aplicaciones basadas en archivos. Establezca
cuales eran esas dificultades:
( ) Independencia en los programas de los archivos de datos, redundancia de datos, dificultad de
mantenimiento
(X) Dificultad de mantener la integridad de los datos, dependencia en las aplicaciones de los
archivos de datos, redundancia
( ) Los datos solo se encuentran en un fichero, dificultad de mantenimiento, falta de seguridad y
ausencia de redundancia
( ) Los cambios en los archivos de datos obliga a modificar los programas que los utilizan, los
datos no son accesibles para las aplicaciones, no se tienen datos que no aporten información
2.
Construye un árbol-B de grado m=5 que almacene un número n=17 de elementos y que tenga la
mayor profundidad posible. Supón que los elementos del árbol son números naturales, y escoge los n
que quieras para formar parte del árbol.
9
3
1
3.
2
6
4
5
12
7
8
10
11
15
13
14
16 17
Dadas las siguientes funciones de complejidad, establece el orden de inclusión correcto entre los conjuntos O(f) (debes dar una secuencia de inclusiones de la forma O(f ) ⊂ O(g) ⊂ O(h) ⊂ . . . ) :
f1 (n) = log22 n
f2 (n) = 23 log2 n
f3 (n) = 6n1/2
f4 (n) = n3 + 2n + 4
f5 (n) = 2n
f6 (n) = 10n2 + 6n
f7 (n) = 3n log4 n
Escribe aquı́ la secuencia correcta de inclusiones:
O(f2 ) ⊂ O(f1 ) ⊂ O(f3 ) ⊂ O(f7 ) ⊂ O(f6 ) ⊂ O(f4 ) ⊂ O(f5 )
Convocatoria: Junio 2005
Estructuras de datos II.
4.
6
Para cada una de las implementaciones de tablas mencionadas, debes decir el orden de complejidad en
el peor caso para la operación de borrado de un elemento:
Vector ordenado : O(n)
Árbol AVL : O(log n)
Árbol de búsqueda : O(n)
Vector de booleanos : O(1)
( n denota el número de elementos amacenados en la tabla)
5.
Supóngase que se decide implementar el TAD matrices utilizando tablas hash con direccionamiento
abierto. Supóngase también que es asumible el declarar como tamaño máximo de la tabla la cantidad
n × m, siendo n y m el máximo número de filas y columnas de cualquier variable de dicho TAD
matrices.
Escoger el tipo de claves y una función hash con las que instanciar el paquete de tablas de manera
que se minimice la complejidad de las operaciones Almacenar y Recuperar (operaciones del TAD
matriz). Se puede considerar que el TAD de matrices se ha instanciado con 1 . . . n y 1 . . . m como
Tipo Indice Filas y Tipo Indice Columnas respectivamente. ¿Cuál es la complejidad en el peor caso
de ambas operaciones?
Asumimos que la longitud de la tabla es n × m.
Las claves son pares de ı́ndices (i, j), donde i indica la fila y j indica la columna.
Como función hash que garantiza que no se producirán colisiones podemos utilizar la que aplana la
matriz por filas, es decir: f (i, j) = (i − 1) × m + j.
Con esta elección garantizamos complejidad O(1) en el peor caso para ambas operaciones.
6.
Se tiene una tabla hash con direccionamiento abierto de tamaño 10. Inicialmente la tabla está vacı́a.
Asumimos que la clave de los elementos de la tabla es un número natural, que la función hash
es hash(clave) = clave M OD 10, y que resolvemos los conflictos siguiendo la estrategia lineal
(Siguiente(P os) = (P os + 1) mod 10). Dibujar la tabla resultante de insertar, en este orden, las claves
13, 45, 22, 63, 3, 19 (omitimos el campo correspondiente a la información asociada a cada clave, por
ser irrelevante para la ejecución de las operaciones). A continuación, eliminar la clave 63 e insertar la
clave 3. Pintar la tabla resultante de la ejecución de estas dos últimas operaciones.
0
1
V
V
0
1
V
V
2
3
4
5
22
13
63
45
3
O
O
O
O
O
6
7
V
2
3
4
5
6
22
13
3
45
3
O
O
O
O
8
L/V
V
7
V
9
8
V
19
Clave
O
Estado
9
19 Clave
O
Estado
Documentos relacionados
Descargar