Professional Documents
Culture Documents
de datos
Especificacin e implementacin
Xavier Franch Gutirrez
Fatos Xhafa
P01/75001/00075
FUOC P01/75001/00075 Tipos abstractos de datos
ndice
Introduccin............................................................................................... 5
Objetivos...................................................................................................... 8
1. Breve resumen de la programacin orientada a objetos........... 9
2. Una jerarqua de TAD......................................................................... 11
2.1. Los contenedores............................................................................... 12
2.1.1. Concepto de contenedor ....................................................... 12
2.1.2. Contenedores recorribles....................................................... 14
2.1.3. Contenedores acotados.......................................................... 14
2.1.4. La jerarqua de elementos...................................................... 15
2.1.5. Conclusin............................................................................. 16
2.2. Una primera clasificacin de los contenedores................................. 17
2.2.1. Las secuencias......................................................................... 19
2.2.2. Los rboles binarios................................................................ 20
2.2.3. Los conjuntos......................................................................... 22
2.2.4. Las funciones.......................................................................... 22
2.2.5. Las relaciones......................................................................... 23
2.3. Traduccin de la jerarqua a Java...................................................... 26
2.3.1. Simulacin de la genericidad................................................. 27
2.3.2. Simulacin de la herencia mltiple....................................... 27
2.3.3. Otras cuestiones..................................................................... 29
3. Implementacin de TAD.................................................................... 30
3.1. Representacin del TAD .................................................................... 31
3.1.1. Los atributos del TAD............................................................. 31
3.1.2. El invariante de la representacin.......................................... 31
3.2. Codificacin de las operaciones........................................................ 32
3.3. Escritura de implementaciones en Java............................................. 33
4. Eficiencia de las implementaciones................................................ 35
4.1. Eficiencia temporal ............................................................................ 38
4.2. Eficiencia espacial .............................................................................. 42
5. Representacin de contenedores usando vectores....................... 44
5.1. Representacin secuencial ................................................................. 44
5.1.1. Presentacin........................................................................... 44
5.1.2. Una primera representacin secuencial ................................. 46
5.1.3. Una segunda representacin secuencial ................................ 48
5.1.4. Representaciones secuenciales marcadas............................... 49
5.1.5. Representaciones secuenciales ordenadas.............................. 51
5.2. Representaciones encadenadas.......................................................... 53
5.2.1. Algunas variantes de representaciones encadenadas............. 57
5.3. Tabla comparativa de las implementaciones vistas.......................... 58
6. Implementacin de TAD con una memoria dinmica............... 59
6.1. La memoria dinmica en Pascal ........................................................ 60
6.2. La memoria dinmica en Java........................................................... 62
6.3. La asignacin y la igualdad ............................................................... 63
6.4. Riesgos del uso de la memoria dinmica........................................... 65
Resumen....................................................................................................... 67
Actividades.................................................................................................. 69
Ejercicios de autoevaluacin.................................................................. 69
Solucionario................................................................................................ 71
Glosario........................................................................................................ 74
Bibliografa................................................................................................. 75
FUOC P01/75001/00075 Tipos abstractos de datos
FUOC P01/75001/00075 5 Tipos abstractos de datos
Introduccin
En este mdulo presentamos el concepto de tipo abstracto de datos (TAD),
que acta como un eje vertebrador de los contenidos de la asignatura. Hace-
mos una breve presentacin del concepto, detallamos qu TAD se desarrollan
durante la asignatura y nos centramos en la nocin de implementacin de los
TAD, mostrando las estrategias ms habituales para construirlos. Como parte
de este ltimo punto, presentamos el mecanismo de memoria directa presente
en todos los lenguajes de programacin modernos, y en particular, en los len-
guajes orientados a objetos.
Un tipo abstracto de datos se define como un dominio de valores sobre los que
se pueden aplicar una o ms operaciones, que tambin forman parte del TAD.
El concepto de TAD es la evolucin natural de la nocin ms primitiva detipos
de datos, propia de los programas de los aos sesenta, que se centraban en los
valores y obviaban las operaciones.
Trabajando con TAD, los nuevos tipos de datos se manipulan mediante unas
operaciones que se introducen al mismo tiempo (de hecho, las operaciones se de-
finen antes de escribir la representacin del tipo), y de esta manera se evita la dis-
persin del cdigo que involucra un TAD. Si, adems, la definicin del TAD se
encapsula en un mdulo compilable de forma separada, se obtiene un producto
final claramente estructurado, fcilmente analizable, robusto, mantenible.
El concepto de TAD ya se present en la asignatura Fundamentos de programa-
cin II, en la que se destacaba la similitud que presenta con respecto a la nocin
de clase en la orientacin a objetos, de la que en realidad es predecesora.
En esta asignatura consideramos que una clase es el mecanismo de encapsula-
miento de un TAD (es decir, la construccin sintctica que lo contiene), dado
que una clase tambin se puede usar con otros significados.
Un TAD consta de dos partes:
1) Laespecificacin. Introduce las operaciones de TAD (nombre e interfaz) y
fija su comportamiento*. El comportamiento se puede determinar de diferen-
tes maneras: mediante comentarios informales, mezclando explicaciones in-
formales y formales, o mediante especificaciones totalmente formales. En esta
asignatura explicaremos el comportamiento de cada operacin de una forma
informal y, a la vez, daremos una especificacin ms precisa, basada en el mo-
delo matemtico del TAD.
2) La implementacin. Determina una representacin de los valores del
TAD y la codificacin de las operaciones de acuerdo con esta representacin.
Abreviamos la expresin tipo
abstracto de datoscon la sigla TAD.
Otros significados
de las clases
La clase System.out de Java
no es un TAD, sino slo una
coleccin de mtodos interre-
lacionados.
* Por ejemplo, podemos tener
un TAD conjunto con operaciones
de conjunto vaco, aadir
elemento, etc.
FUOC P01/75001/00075 6 Tipos abstractos de datos
Larepresentacin consistir en elegir una estructura de datos adecuados para la
especificacin dada y un predicado de correccin*. Veremos que es importante
la eleccin de una representacin adecuada de valores, dados los requisitos del
TAD, principalmente por lo que se refiere a la eficacia en tiempo y en espacio.
Desde el momento en que queremos estudiar los TAD dentro del marco de la
orientacin a objetos, es conveniente organizarlos segn una jerarqua de cla-
ses adecuada. La jerarqua de tipos abstractos de datos est diseada no slo
para incorporar todos los TAD aqu vistos, sino para poder extenderla a otros
TAD que, por motivos de carga docente, no se presentan en la asignatura.
Para construir esta jerarqua usaremos todos los conceptos de la orientacin a
objetos vistos en la asignatura Fundamentos de programacin II, que se repasan
brevemente en la primera seccin de este mdulo. Veremos que la herencia
nos ayuda a definir los TAD por especializacin, de forma que un TAD se ob-
tiene despus de un proceso de refinamiento.
La raz modeliza el concepto general de contenedor de datos; puede ser de
cinco tipos principales: secuencias, rboles binarios, conjuntos, funciones y
relaciones. Cada uno de stos se refina a su vez en otros, ms concretos, que
forman los TAD (que se estudian individualmente en otros mdulos de la asig-
natura). Hay que mencionar que, a partir del concepto bsico de contenedor,
se definen diferentes especializaciones que presentan algunas variantes habi-
tuales de esta nocin. El resultado es la existencia (por lo menos conceptual)
de distintas jerarquas paralelas.
La jerarqua se desarrolla sin pensar en las restricciones que un lenguaje orien-
tado a objetos particulares puede imponer sobre los mecanismos utilizados.
Ahora bien, dado que seguiremos usando Java como un lenguaje de trabajo de
la asignatura, estudiamos tambin cmo hay que adaptar la jerarqua a las par-
ticularidades de este lenguaje, especialmente por lo que se refiere a la ausencia
de genericidad y de herencia mltiple entre clases.
El resto de los mdulos se dedica al estudio de cuestiones relacionadas con la
implementacin de los TAD. Primero, se enumeran y se estudian las distintas
partes que forman una implementacin, como ya hemos mencionado. Tam-
bin aqu se opta por utilizar una notacin algortmica, similar a la que ya co-
nocis, y entonces se nombran las restricciones y particularidades de Java.
A continuacin, nos enfrentaremos al problema de medir las implementaciones
construidas. Tomamos la eficiencia como un criterio de medida, es decir, el
tiempo de ejecucin de las operaciones que se tienen que llevar a cabo, el espa-
cio necesario para representar el tipo y, eventualmente, el espacio adicional que
necesitan las operaciones cuando se ejecutan. Discutiremos la unidad de medi-
da de la eficiencia y detallaremos las reglas bsicas que permiten calcularla a par-
tir de los constructores de tipo e instrucciones que forman la implementacin.
* Por ejemplo, podemos
implementar un conjunto
con vectores, con memoria
dinmica, etc.
Un contenedor es un almacn
de datos de cualquier tipo.
Consultad los TAD individuales
estudiados en los mdulos
Secuencias y rboles, Funciones
y conjuntos y Relaciones de esta
asignatura.
Consultad la notacin algortmica
utilizada en la asignatura
Fundamentos de programacin I.
Necesidad de medir
las implementaciones
Es necesario medir las implemen-
taciones no slo para conocer
con detalle las caractersticas,
sino tambin para elegir la ms
adecuada cuando un TAD tiene
ms de una.
FUOC P01/75001/00075 7 Tipos abstractos de datos
Por ltimo, introduciremos las estrategias generales de representacin de TAD
que usaremos a lo largo del curso, clasificadas en dos familias:
a) Lasestrategias secuenciales se caracterizan por el hecho de que la estructura
de datos que aparece en la representacin (tpicamente, un vector) se divide
conceptualmente en dos partes, la parte libre y la parte ocupada, que contiene
todos los elementos consecutivos segn un criterio determinado*. Veremos va-
rias variantes de estas estrategias.
b) Por lo que se refiere a las estrategias encadenadas, introduciremos el con-
cepto general que se basa en romper esta continuidad de los elementos, y des-
pus nos centraremos en su implementacin usando la memoria dinmica del
ordenador.
Estas estrategias generales se adaptarn a los TAD concretos, o se complemen-
tarn con tcnicas ms especficas.
La memoria dinmica es un espacio de datos que se adapta al crecimiento y
decrecimiento de las estructuras de datos que implementan los TAD. A diferen-
cia de los vectores, el espacio de la estructura no est predeterminado. Cuando
se inserta un elemento, el cdigo de la operacin reclama el espacio necesario
para almacenarlo, y cuando se destruye, el espacio se libera (en algunos lengua-
jes de forma implcita, en otros explcitamente). Estudiaremos tanto los efectos
positivos como los negativos del uso de memoria dinmica, en comparacin
con los vectores.
* Tpicamente, orden de entrada
en el contenedor u ordenacin
segn un campo (entero o cadena
de caracteres, normalmente).
FUOC P01/75001/00075 8 Tipos abstractos de datos
Objetivos
Los materiales asociados a este mdulo didctico permitirn al estudiante al-
canzar los siguientes objetivos:
1. Asimilar el concepto de tipo abstracto de datos (TAD) y su relacin con los
conceptos propios de la orientacin a objetos.
2. Entender los principios bsicos de la programacin por diferencias median-
te el estudio de la jerarqua de TAD de la asignatura.
3. Obtener una primera panormica de todos los TAD que se estudiarn du-
rante la asignatura y entender las diferencias esenciales que presentan.
4. Conocer las partes que componen una implementacin de TAD.
5. Entender el significado de la notacin asinttica O-grande como criterio
para medir la eficiencia y ser capaces de aplicar su definicin en el clculo
de la eficiencia de las implementaciones de TAD y algoritmos que veremos
a lo largo de la asignatura.
6. Disponer de un marco de trabajo para la definicin de representaciones
particulares de TAD.
7. Conocer el concepto de memoria dinmica y su funcionamiento concreto
en dos lenguajes de programacin diferentes.
8. Profundizar en el conocimiento del lenguaje de programacin Java, espe-
cialmente en lo concerniente a la definicin de jerarquas y a la implemen-
tacin de TAD.
FUOC P01/75001/00075 9 Tipos abstractos de datos
1. Breve resumen de la programacin orientada
a objetos
En otra asignatura se ha definido la orientacin a objetos como un paradigma
de programacin basado en la encapsulacin y la ocultacin de la informa-
cin, la abstraccin y la clasificacin, y el polimorfismo y la herencia.
Algunas clases no permiten crear instancias. Los motivos pueden ser dos (no
exclusivos): que existe algn mtodo sin implementar, o bien que la clase ca-
racteriza ciertas propiedades del dominio. En el primer caso hablamos de cla-
ses diferidas (y mtodos diferidos), y en el segundo, de clases abstractas.
Tambin conviene recordar la existencia de clases genricas (clases parame-
trizadas), en las que el tipo de determinantes atribuidos est sin concretar. Su
utilidad es enorme, porque permiten definir categoras similares de clases de
una sola vez.
En esta asignatura, y dadas la definicin de clase y las caractersticas menciona-
das, usamos las clases como un mecanismo de encapsulacin de los TAD.
En este contexto, aadimos algunas clasificaciones adicionales de las clases.
Primero, distinguimos las clases de especificacin y las clases de implemen-
tacin. Las primeras encapsulan especificaciones de TAD y tomarn la forma
de clases diferidas sin ningn mtodo implementado. Las segundas encapsu-
lan las implementaciones y tendrn todos los mtodos implementados.
Los atributos y mtodos de las clases tienen asociado un mbito, que indica el
grado de acceso que tienen sobre este elemento las diferentes clases que con-
figuran el programa. Los mbitos pueden ser de tres tipos: privado (local de
la clase), protegido (permite el acceso a los herederos de la clase) y pblico
(acceso libre). La definicin correcta de los mbitos es primordial para asegurar
la buena programacin y para respetar el principio de ocultacin de la infor-
macin (que controla el acceso a los recursos de la clase).
Laclase es la unidad bsica de encapsulacin, que combina estructural-
mente un conjunto de datos (representados por atributos) y un conjun-
to de operaciones (o mtodos).
Losobjetos que interaccionan en los programas construidos con lengua-
jes orientados a objetos son instancias de clases: slo pueden tomar los
valores permitidos por la clase, y slo se les puede aplicar mtodos de cla-
se. Los objetos se crean mediante los llamados mtodos constructores,
y se destruyen tambin mediante mtodos o bien de forma implcita.
Consultad la definicin de orientacin
a objetosen la asignatura
Fundamentos de programacin II.
Consultad los conceptos de
especificacin e implementacin de
un TAD en la introduccin de este
mdulo didctico.
En Java
las clases de especificacin
tomarn la forma de interfaces
en lugar de clases.
FUOC P01/75001/00075 10 Tipos abstractos de datos
Las clases se conectan segn varias formas de relacin. La herencia es la rela-
cin ms caracterstica: cuando una clase A hereda de una clase B, todos los
atributos y mtodos no privados de B lo son tambin de A. Adems, A puede
redefinir mtodos y aadir otros nuevos. La herencia favorece la llamada pro-
gramacin por diferencias, que enfatiza la identificacin de las diferencias que
existen entre las clases.
Conviene tener presentes algunos casos particulares de herencia. Primero, la he-
rencia mltiple, en la que una clase hereda ms de una. Es necesario determi-
nar qu pasa con los mtodos que se heredan ms de una vez. Un caso particular
de herencia mltiple es la herencia repetida, en la que una clase hereda de otra
ms de una vez*.
Si consideramos todas las clases relacionadas por herencia, podemos formar
jerarquas de clase, que denotan todas las interrelaciones existentes. Las jerar-
quas de clases conforman una representacin estructurada de los dominios
del conocimiento.
El polimorfismo es una caracterstica ineludiblemente asociada a la herencia
y se refiere a las distintas formas que puede tomar un objeto dependiendo de
cmo se construye. Cuando se ejecuta el programa, un objeto declarado de una
claseA puede crearse mediante una operacin constructora de una clase here-
dera de A. Entonces los mtodos aplicados al objeto en realidad se determinan
en tiempo de ejecucin, cuando realmente se sabe la forma que ha tomado el
objeto; es lo que se denomina vinculacin dinmica.
Al menos hemos recuperado el vocabulario orientado a objetos. Si hay algo
que no os queda claro, repasad los apuntes de Fundamentos de programacin II;
todo lo dicho aqu aparece en este material. Ahora ya podemos empezar con
la asignatura.
* Diferentes lenguajes presentan
varios tratamientos de esta
situacin.
FUOC P01/75001/00075 11 Tipos abstractos de datos
2. Una jerarqua de TAD
Los mecanismos de la orientacin a objetos que hemos visto nos permiten es-
tructurar los programas en clases interrelacionadas, as como formar libreras
temticas de TAD reutilizables encapsuladas en clases. Este segundo punto es
precisamente el que aqu nos interesa.
El objetivo de este apartado es ofrecer un catlogo verstil de TAD, encapsula-
dos en clases genricas y organizados jerrquicamente, para poder gestionar co-
lecciones de elementos segn diferentes polticas de acceso. En esta jerarqua
usamos varios criterios de clasificacin, que permiten comprender las diferen-
cias entre los TAD disponibles. Durante el desarrollo utilizaremos la herencia
para representar especialmente una relacin: la especializacin. De esta forma,
cuando los programas necesiten almacenar conjuntos de elementos, podrn
reutilizar los TAD de esta librera, idealmente sin ninguna modificacin, o bien
creando un nuevo TAD encapsulado en una nueva clase, como una especiali-
zacin de uno o varios TAD ya existentes.
Hay que indicar que no incluimos las clases de implementacin en la jerarqua,
de forma que stas son, pues, clases diferidas que podrn ser abstractas o no.
Empezaremos por introducir el concepto de contenedor como nexo de todos los
TAD que forman parte de una jerarqua, y veremos distintas variantes de este
concepto. Despus daremos una primera clasificacin de los TAD resultantes en
cinco tipos principales. Estudiaremos estas cinco clases, comentaremos unos
cuantos aspectos interesantes y entenderemos la aparicin de ciertos criterios
recurrentes. El estudio detallado se expone en los mdulos Secuencias y rbo-
les, Funciones y conjuntos y Relaciones de esta asignatura.
Antes de empezar, expresaremos unos breves comentarios:
1) En las clases slo se incluyen las operaciones indispensables para caracteri-
zar los TAD definidos.
2) La jerarqua se mantiene dentro de unos lmites manejables dada la carga
docente de la asignatura.
3) Por motivos de espacio, y tambin para no caer en la monotona, la jerar-
qua no se presenta de forma completa.
4) Los TAD aparecen en los otros mdulos de la asignatura de forma indivi-
dual. En este mdulo ofrecemos una panormica general que nos ayudar a
comprender la misin de cada tipo, y ms adelante, tendremos una descrip-
cin ms individualizada que resumir las caractersticas que poco a poco se
van aadiendo, principalmente mediante la herencia.
Recordad que el concepto de
librera de clases se ha introducido
en la asignatura Fundamentos
de programacin II.
Recordad que la utilidad de la
orientacin a objetos en el contexto
de la reutilizacin de softwarese ha
estudiado en la asignatura Fundamentos
de programacin II.
Podis obtener una panormica
general de la jerarqua Contenedor
en el material del aula
de esta asignatura.
Como se indica en la actividad 1, hay
otros TAD, as como ampliaciones y
variantes de los TAD estudiados, cuya
existencia aumentara la versatilidad
de la librera.
Podis ver la actividad 2
de este mdulo didctico.
FUOC P01/75001/00075 12 Tipos abstractos de datos
2.1. Los contenedores
Aqu definiremos el concepto de contenedor y describiremos los principales
tipos de contenedores existentes.
2.1.1. Concepto de contenedor
El concepto de contenedor es muy general; lo representamos mediante una
clase diferida parametrizada:
diferida, porque algunos mtodos no se pueden implementar;
parametrizada, porque el comportamiento del TAD es independiente de los ti-
pos de elementos almacenados. El parmetro es la clase de elementos que se de-
ben almacenar, sin ningn requisito adicional, excepto que se pide la existencia
de una funcin que permita adivinar si dos elementos son iguales. Hay algunos
tipos particulares de contenedores que s formulan alguna restriccin adicional
sobre los elementos (por ejemplo, que formen un dominio ordenado), pero esta
clase de requisitos tendr que aparecer localmente all donde haga falta.
En general, cualquier contenedor estar caracterizado por tres tipos de operacio-
nes: insercin, supresin y algn tipo de consulta sobre elementos individuales.
La forma que tomarn estas operaciones puede ser muy diferente dependiendo
del tipo de contenedor.
Ejemplos de operacin de insercin en un contenedor
Consideremos la operacin de insercin. Si bien la mayora de los contenedores inserta
un valor en un solo contenedor, hay TAD en los que el valor consta de dos componentes
(por ejemplo, un contenedor que relacione a personas y empresas) que dan lugar a dos
parmetros diferentes en la interfaz de la operacin. En otros, se exige la existencia de
una clave que identifique los elementos (por ejemplo, contenedores de personas identi-
ficadas por el DNI). Tambin pueden existir varias operaciones de insercin (por ejemplo,
insercin en el inicio e insercin en el final en contenedores ordenados). Por este motivo,
en la definicin ms abstracta de los contenedores no puede haber una sola forma comn
con la operacin de insercin.
As pues, cules son los servicios que debe definir la clase Contenedor conce-
bida como la raz de la jerarqua de clases? En general, lo nico que podemos
decir de los contenedores es lo siguiente:
1) Debe ser posible crearlos y destruirlos; por este motivo tendremos una ope-
racin para crear el contenedor vaco y otra para destruir el contenedor creado.
2) Todo contenedor tendr una ocupacin determinada; por eso definimos un
atributo, tamao, que registra el nmero de elementos que estn contenidos. Se
define como atributo protegido (as, todos los TAD de la jerarqua podrn ac-
ceder a ste, pero no sus usuarios) y, en consecuencia, hay que definir un nuevo
Denominaremoscontenedor cualquier TAD que se caracterice por con-
tener un conjunto de elementos.
En el anexo de este mdulo
encontraris la implementacin en
Java de algunos contenedores de los
que se presentan.
Ejemplos de contenedores
Un TAD para registrar a los so-
cios de un club; un TAD para
guardar las direcciones web de
una hiperagenda; un TAD para
guardar un conjunto de iconos,
etc. Todos estos TAD son casos
particulares de contenedores.
Otras operaciones
de los contenedores
Adems de las operaciones
bsicas, los contenedores
ofrecern otras: creacin,
destruccin, predicados,
recorridos, y otras ms
especficas.
Atributos protegidos
Recordad que un atributo
protegido es aquel sobre el cual
slo se tiene acceso en la clase
que lo define y en sus herederas.
FUOC P01/75001/00075 13 Tipos abstractos de datos
mtodo que devuelva su valor. Dada su utilidad, definimos an otro mtodo
que indica si el contenedor est vaco o no. Observad que estas dos operaciones
pueden implementarse completamente en funcin del atributo tamao.
3) Sus elementos son todos del mismo tipo (que acta como un parmetro de
la clase), sobre el cual no se pide ms que una funcin para saber si dos ele-
mentos son iguales.
En la figura siguiente se ofrece la representacin en UML de la claseContenedor
y de varias clases herederas que estudiamos en este mdulo. Para anotar expl-
citamente el tipo de parmetro del TAD, usamos la facilidad de UML para aa-
dir nuevos compartimentos en las cajas que representan las clases. UML ofrece
construcciones que permitiran definir los parmetros de forma ms elegante.
Pese a todo, rechazamos su uso para no complicar el temario excesivamente,
y porque la solucin que adoptamos cubre nuestras necesidades.
FUOC P01/75001/00075 14 Tipos abstractos de datos
2.1.2. Contenedores recorribles
Aparte de las operaciones de acceso individual antes mencionadas, otra fun-
cin que pediremos a menudo a los contenedores es la obtencin de todos sus
elementos, a veces siguiendo un orden determinado, a veces en orden aleato-
rio. Estos contenedores los denominaremos contenedores recorribles.
Como paso previo a la definicin de los contenedores recorribles, formulamos
la clase Iterador, que ofrece las cuatro opciones mencionadas. Entonces, los con-
tenedores recorribles se pueden definir simplemente por herencia mltiple de
las clases Contenedor e Iterador.
Fijmonos en que la clase Iterador no establece ningn orden de visita de los
elementos almacenados en el contenedor. Este orden es aleatorio y depende
de factores, en principio, no controlables por el programador (por ejemplo, el
orden de insercin y las estrategias de implementacin del tipo). Sin embargo,
en varios TAD interesa imponer un orden en el recorrido.
Por este motivo definimos la clase heredera deIterador, IteradorOrdenado, que re-
quiere que los elementos sean comparables mediante alguna operacin (es de-
cir, que formen un dominio totalmente ordenado). El efecto de esta restriccin
aparece en el tipo de los elementos, que deja de ser Elem y pasa a ser ElemOrd.
La correspondiente restriccin de orden que aparece en ElemOrd establece las
propiedades de ordenacin que caracterizan este recorrido.
La definicin de los contenedores recorribles ordenadamente es similar a Con-
tenedorRecorrible.
2.1.3. Contenedores acotados
Los TAD contenedores definidos hasta ahora tienen una capacidad infinita: se
puede ir insertando un elemento tras otro sin ningn tipo de restriccin. Esta
situacin no se produce nunca por motivos de implementacin. Muchas veces
usamos vectores para representar los tipos, y entonces tenemos que controlar
que la estructura no se llene por encima de su capacidad. As pues, la imple-
mentacin por vectores no se ajusta a la implementacin dada.
Por eso, si queremos obtener una jerarqua adecuada, debemos tener en cuen-
ta este hecho.
En todos los casos, los contenedores recorribles seguirn el mismo pa-
trn: se situarn sobre el primer elemento, y despus consultarn el ele-
mento actual y avanzarn al siguiente reiteradamente, hasta llegar al final.
El patrn de los contenedores
recorribles es idntico al clsico
recorrido de secuencias que conocis
de la asignatura Fundamentos de
programacin I.
Ejemplo de orden
en el recorrido
Un ejemplo tpico en el que hay
que imponer un orden en el re-
corrido sera el caso en que los
elementos son cadenas de
caracteres, y estas cadenas se
quieren obtener en orden
alfabtico.
Consultad la definicin de ElemOrd
en el subapartado 2.1.4. de este
mdulo didctico.
Causas del agotamiento
del espacio
Una situacin que puede pro-
ducir agotamiento del espacio
se da cuando slo utilizamos
memoria dinmica (introduci-
da en el apartado 6), que va
asignando espacio a medida
que las implementaciones la
necesitan, porque en realidad
la memoria del ordenador no
es infinita.
FUOC P01/75001/00075 15 Tipos abstractos de datos
En la nueva clase, existen varias formas de representar la dimensin mxima
de un TAD acotado:
Se puede aadir a la clase un parmetro formal en la clase que la represente.
Se puede introducir un atributo de clase.
Se puede pasar la dimensin como parmetro de la operacin de creacin.
Optamos aqu por la tercera opcin, a causa de la flexibilidad que nos propor-
ciona: varios objetos de una misma clase se pueden crear con una capacidad
diferente. Tambin influye en la eleccin la facilidad de implementar este es-
quema mediante Java.
En la clase resultante destaca la redefinicin de la operacin de creacin, as
como la aparicin de una nueva operacin para saber si el contenedor est
lleno.
A partir de aqu, combinando con los dos tipos de iterador que hemos visto,
podemos crear dos contenedores recorribles acotados.
2.1.4. La jerarqua de elementos
Como hemos avanzado, a lo largo del apartado se formularn varias restricciones
sobre los elementos que se almacenan en los contenedores. Para estructurar estos
elementos, hemos optado por relacionarlos con la jerarqua UML de la siguiente
figura; pese a que somos conscientes de que los lenguajes orientados a objetos
ms habituales no soportan la definicin de jerarquas sobre los parmetros.
La raz del diagrama es la clase de los elementos sin ninguna otra operacin
que la igualdad. A partir de esta operacin, se definen varias especializaciones:
a) A la clase ElemOrd le aadimos una operacin de orden total, especialmen-
te til en el caso ya visto de los iteradores ordenados.
b) La clase ElemEsp simplemente identifica un elemento especial dentro del
dominio, que puede servir de indicador en diferentes situaciones*.
c) Para cerrar este primer nivel, la clase ElemClave define los elementos en los
que se puede distinguir una clave que los identifica; la funcin f es la que per-
mite obtener la clave del elemento*.
La clase ContenedorAcotado, heredera de contenedor, se introduce para
controlar que no se produzca un desbordamiento en esta familia de TAD.
* Por ejemplo, una persona
sin DNI identifica un caso especial
de persona.
* Por ejemplo, el DNI
de una persona.
FUOC P01/75001/00075 16 Tipos abstractos de datos
En un segundo nivel, por herencia mltiple de estas nuevas clases, obtenemos
tres ms:
a) Primero, la clase ElemOrdClave, que permite comparar las claves de los ele-
mentos de ElemClave.
b) Tambin, ElemClaveEsp, en el que la clave tiene un valor especial, que uti-
lizaremos sobre todo como un indicador de inexistencia de un elemento en
un contenedor.
c) Por ltimo, ElemSum, que hereda de ElemOrd y ElemEsp y, adems, aade
una operacin de suma de los elementos, as como un segundo elemento es-
pecial; esta clase nos permitir asignar pesos a los elementos.
Finalmente, definimos una clase llamada ElemClaveEspOrd, de comportamien-
to combinado segn las clases de las que hereda.
2.1.5. Conclusin
Del estudio de este apartado se puede llegar a la conclusin de que el concep-
to de contenedor es el eje vertebrador del estudio de los TAD que llevaremos
a cabo en esta asignatura, as como de que la nocin bsica se puede adaptar
FUOC P01/75001/00075 17 Tipos abstractos de datos
segn algunos criterios que se han visto aqu (capacidad acotada y recorrido)
y otros que no se mencionan (por ejemplo, contenedores persistentes o no).
Un efecto de esta variedad de contenedores es el siguiente: la mayora de los
TAD que veremos se puede definir en realidad segn todas estas variedades. Por
eso, se puede imaginar que hay, ms que una nica jerarqua de TAD, varias je-
rarquas paralelas que slo cambian en la raz (la clase concreta de contenedor).
Est claro que esta diferencia resulta fundamental, dado que todas las clases de
una de estas jerarquas heredan los atributos, mtodos y restricciones propios de
su raz correspondiente.
En la mayor parte de la asignatura nos centraremos en la jerarqua que de-
pende de la clase bsica Contenedor, si bien en algunos puntos nos referire-
mos al resto de las jerarquas, tanto por el hecho de que existen TAD que
carecen de sentido si no se pueden recorrer como por el hecho de tener ejem-
plos de diferentes tipos.
2.2. Una primera clasificacin de los contenedores
Dada su funcionalidad, distinguimos cinco clases principales de contenedo-
res, clases que presentamos a continuacin. Como no poda ser de otra forma,
todos provienen de la implantacin de conceptos matemticos clsicos.
Contenedor persistente
Entendemos por contenedor
persistente aquel que conserva
los datos entre diferentes eje-
cuciones de un programa.
FUOC P01/75001/00075 18 Tipos abstractos de datos
1) Las secuencias representan disposiciones lineales de elementos. Se carac-
terizan por la existencia de un primer elemento, un ltimo elemento y una po-
ltica de acceso a los elementos siguiendo este orden lineal. Por este motivo,
las supresiones y las consultas afectan a unos elementos determinados por el
contenido mismo de la estructura. Los elementos se aaden de uno en uno.
En este nivel de abstraccin, y a causa de la diversidad de secuencias que estu-
diaremos, no se puede establecer ninguna propiedad que se refiera a estas ope-
raciones que sea igual para todas, excepto los errores de borrar o consultar en
una secuencia vaca.
2) Los rboles binarios nos sirven para introducir relaciones jerrquicas en un
dominio de elementos. Cada elemento est por encima de dos ms, como mucho,
y est por debajo de un tercero (salvo un elemento especial, la raz del rbol, que
no est por debajo de ningn otro). Esta relacin se hace patente en la signatura
de la operacin insercin (enraiza), que involucra a dos rboles y no slo a uno.
La operacin de supresin es en realidad doble (hizq y hder) y no afecta a un
nico elemento, sino a varios. La consulta obtiene siempre el elemento ms
relevante de la jerarqua, es decir, la raz. La clase es diferida pero no abstracta,
dado que el comportamiento de las operaciones est completamente determi-
nado por las restricciones correspondientes.
3) Losconjuntos son la tercera clase de contenedor disponible. Hay una ope-
racin conmutativa para aadir elementos. La operacin de suprimir, por su
parte, no viene dada por la estructura misma como suceda en las dos catego-
ras anteriores, dada la ausencia de orden en la disposicin de los elementos
dentro del contenedor, sino que tenemos una operacin que explicita el ele-
mento que se debe suprimir. No se considera error suprimir un elemento que
no aparece, pese a que este punto es muy arbitrario. Finalmente, la operacin
de consulta se identifica con la pertenencia de los elementos a los conjuntos.
4) Las funciones son la cuarta familia de contenedores y se caracterizan por
la existencia de un segundo dominio de elementos. El contenedor se ocupa de
asociar un valor de este segundo dominio (alcance de la funcin) a todo ele-
mento del primero que aparezca (dominio de la funcin).
Por este motivo, la insercin implica pares de elementos, uno de cada dominio,
y se establecen dos propiedades que cualquier heredero de la clase debe cumplir:
La primera establece que la insercin de un par provoca que cualquier aso-
ciacin anterior para su primer elemento quede anulada.
La segunda afirma que, en cualquier caso, la insercin es conmutativa.
La supresin y la consulta se llevan a cabo de acuerdo con el primer elemento
del par insertado. La supresin y consulta de elementos que no estn en la fun-
cin es un error (la funcin es parcial), aunque algunas clases herederas rela-
jarn esta condicin.
FUOC P01/75001/00075 19 Tipos abstractos de datos
5) Por ltimo, hay una familia de contenedores que permite establecer relacio-
nes binarias entre pares de elementos. Al igual que suceda en las funciones, hay
dos dominios de elementos involucrados en el contenedor, y las operaciones de
aadir y borrar se refieren en este caso al establecimiento o ruptura de interrela-
ciones entre elementos de los dos dominios (si bien algunas especializaciones
tambin permitirn aadir y borrar elementos en los mismos dominios). La con-
sulta slo comprueba que se establecen interrelaciones entre un par de elementos.
Dada su necesidad en la prcticamente totalidad de algoritmos que involucran
relaciones binarias, existen operaciones para obtener todos los elementos de un
dominio relacionados con un elemento de otro. Dado que se trata de dos reco-
rridos posibles, conviene heredar dos veces de los iteradores, obtenindose dos
conjuntos de operaciones de recorrido (posiciona 1,...; posiciona 2,...). Es nece-
sario redefinir posiciona, pues aqu se necesita un parmetro de referencia.
Encontramos una especializacin particularmente relevante en el caso de que
los dos dominios sean el mismo. Hablamos entonces de grafos. En este caso,
a las operaciones habituales le aadimos otras muy especficas que provocan
diferentes algoritmos de inters.
En el resto de este subapartado desarrollaremos un poco ms los contenedores
que hemos presentado aqu. El estudio detallado de stos, especialmente por
lo que se refiere a las tcnicas de implementacin, es el ncleo de otros mdu-
los de la asignatura.
2.2.1. Las secuencias
Como ya hemos comentado, las secuencias distribuyen un dominio de elemen-
tos segn una relacin lineal. Es decir, todo elemento dentro de una secuencia
tiene un elemento anterior (excepto el primero) y un elemento posterior (excep-
to el ltimo). En algunas clases de secuencias, el anterior y el sucesor de un ele-
mento pueden cambiar a medida que la estructura evoluciona; en otras, no.
Podemos imaginar muchos TAD que responden a la descripcin de la secuen-
cia dada. Aqu nos limitaremos a introducir los cuatro ms habituales.
Para empezar, las pilas y las colas son los dos ms simples. En estos TAD las
operaciones slo afectan a los extremos de la secuencia. En la pila, se borra y
consulta el ltimo elemento insertado; en la cola, el primero que se insert.
Ejemplos de usos de pilas y colas
Las pilas se pueden utilizar para implementar funciones recursivas de forma eficiente; las
colas se utilizan para organizar los trabajos lanzados a una cola de impresin.
Una variante de las colas muy utilizada son las denominadas colas priorita-
rias, en las que la posicin que ocupa un elemento dentro de la cola viene
dada por su prioridad y no por el orden de insercin. Por eso, se formula un
Nomenclatura
Para distinguir, utilizamos el
trmino relacin para el TAD
e interrelacin para la relacin
establecida entre dos elemen-
tos de los dominios.
Consultad los mdulos Secuencias
y rboles, Funciones y conjuntos
y Relaciones de esta asignatura.
FUOC P01/75001/00075 20 Tipos abstractos de datos
requerimiento adicional sobre los elementos, que provoca un cambio en el pa-
rmetro del TAD: los elementos deben ser comparables.
Ejemplo de uso de colas prioritarias
Una cola prioritaria se puede utilizar para gestionar el orden de ejecucin de los trabajos en
un sistema multiusuario en el que el procesador se asigna segn la importancia de las tareas.
Por ltimo, introducimos el TAD de las listas con punto de inters (o, para
abreviar, listas), que representa el concepto ms general de secuencia: los ele-
mentos se pueden insertar en cualquier lugar de la secuencia, y se puede borrar
y consultar cualquier elemento. Con este objetivo se define TAD no como un
contenedor simple, sino como un contenedor recorrible. La herencia mltiple
nos permite plasmar este nuevo TAD de forma simple y elegante.
2.2.2. Los rboles binarios
El TAD de los rboles binarios, tal como se ha descrito, tiene un modelo com-
pletamente definido que se puede implementar segn diferentes estrategias
que veremos ms adelante.
Partiendo de este TAD, podemos definir una variante que consiste en aadirle
las operaciones de recorrido, heredando otra vez de ContenedorRecorrible. El re-
sultado es la clase de los rboles recorribles.
Observacin
En lugar de proponer la restric-
cin de comparacin sobre los
elementos, se podra haber re-
querido una funcin que, dado
un elemento, retornase su priori-
dad (un entero), y entonces se
podran comparar directamente.
Observad que
las dos operaciones de con-
sulta de las listas (heredadas
deContenedorRecorrible
y Secuencia) son la misma.
En realidad...
... las operaciones aade
y consulta de ColaPrioritaria no
ocultan las anteriores, que
siguen existiendo.
FUOC P01/75001/00075 21 Tipos abstractos de datos
Fijmonos en una diferencia con respecto a las listas: el punto de inters no se
considera relevante para las operaciones de construccin y destruccin del r-
bol, slo lo es para la consulta.
De hecho, esta clase an no determina cmo se obtienen los nodos del rbol,
dada la ausencia de restricciones; la clase todava est indefinida. Posterior-
mente veremos que existen varias polticas de obtencin de los elementos del
rbol; en consecuencia, decidimos introducir una clase para cada una, en las
que ya s aparecen las restricciones que determinan el orden.
Finalmente, para los casos en que sea necesario tratar un mismo rbol con va-
rios recorridos, definimos una ltima clase que los ofrece todos. Esta clase sim-
plemente hereda de todas las anteriores.
Hay que ir con cuidado con la herencia mltiple: si bien las operaciones de
posicionar, avanzar y preguntar por el final del recorrido se tienen que man-
tener separadas, no sucede igual con la consulta, que tiene el mismo com-
portamiento para todos los recorridos (acceder al elemento distinguido). La
forma correcta de tratamiento a este respecto depende del lenguaje (renom-
brar, prefijar, etc.).
FUOC P01/75001/00075 22 Tipos abstractos de datos
2.2.3. Los conjuntos
Distinguimos dos grandes categoras de conjuntos: los conjuntos como tales
y los conjuntos con repeticiones, a los que llamaremos sacos. En los prime-
ros, los elementos no pueden aparecer repetidos y, en los segundos, s. En los
sacos, la operacin de supresin elimina slo una aparicin de un elemento;
adems, la operacin de pertenencia se complementa con otra para contar el
nmero de apariciones de un elemento.
Como es habitual, sobre estos dos TAD podemos crear las versiones recorri-
bles. A diferencia de las estructuras lineales, el orden de obtencin de los ele-
mentos es aleatorio, y por eso distintas clases de implementacin de estos TAD
pueden tener un comportamiento diferente.
2.2.4. Las funciones
Ya hemos comentado que el TAD de las funciones plasma el concepto de fun-
cin parcial, y por eso la primera y ms inmediata especializacin es definir
por herencia las funciones totales.
Este nuevo TAD, el TAD de las funciones totales, exige que el alcance de la
funcin tenga un elemento especial, que es el resultado que se obtiene cuando
se consulta un elemento que no forma parte del dominio de la funcin. Por
este motivo, el parmetro de este TAD correspondiente al alcance es ElemEsp.
La operacin de existencia se mantiene, aunque ya no tiene la importancia de
antes; su resultado se puede calcular a partir de la consulta.
Las funciones totales son
interesantes porque aseguran
que la consulta siempre
da un resultado vlido.
FUOC P01/75001/00075 23 Tipos abstractos de datos
Otra variante del concepto de funcin (ya sea total o parcial) aparece cuando,
en lugar de relacionar elementos de dos dominios diferentes, uno de los dos
dominios est contenido en el otro*. Una visin equivalente es que la funcin
se convierte en un conjunto de elementos tales que cada elemento tiene una
clave que lo distingue. El vnculo entre los dos dominios se establece mediante
un parmetro f que, dado un elemento, retorna su clave. El conjunto con clave
se construye por herencia redefiniendo la funcin de insercin para que tenga
un nico parmetro, de clase ElemClave (que suministra la funcin f).
Por ltimo, mencionamos que existen varias versiones recorribles para estos TAD.
2.2.5. Las relaciones
Consideramos varias especializaciones del concepto de relacin:
1) La primera especializacin que hacemos de este concepto proviene de la
forma de tratar los dos dominios que lo forman. Como hemos comentado
* Por ejemplo, una funcin que,
dado el DNI de una persona,
proporciona la ficha completa
de sta, incluido el mismo DNI.
FUOC P01/75001/00075 24 Tipos abstractos de datos
anteriormente, la clase Relacin implica que cuando se crea la relacin se co-
nocen ambos dominios y permanecen invariables durante su vida. Sin embar-
go, ste no siempre es el caso. Para cada dominio, la otra situacin posible es
que, cuando se crea la relacin, el dominio est vaco y los elementos se ten-
gan que insertar y borrar explcitamente.
Por eso, definimos dos clases simtricas, considerando esta situacin en cada
uno de los dominios y, finalmente, una ltima clase heredera de estas dos, para
el caso de que los dos dominios sean variables. Las cuatro clases resultantes pue-
den considerarse como un punto de partida de cuatro subjerarquas paralelas
para las relaciones. Nosotros nos centraremos en la primera (los dos dominios
fijos), pero los resultados obtenidos se pueden generalizar al resto de los casos.
Actividad
Una alternativa que no hemos considerado es que implcitamente se vayan aadiendo y
borrando los elementos a medida que aparecen o desaparecen en la relacin.
1. Redefinid la jerarqua que cuelga de la clase Relacin considerando la alternativa que
acabamos de proponer.
2) El siguiente criterio de especializacin ms relevante es la asociacin de pe-
sos, llamados etiquetas, en las interrelaciones.
Las etiquetas, que deben presentar ciertas operaciones para manipularlas c-
modamente (la suma y las comparaciones), se definen en la clase ElemSum.
Motivos para la primera
especializacin de relacin
En el momento de relacionar
a los estudiantes y a las
estudiantes y a los tutores
y tutoras de la UOC, debemos
tener presente que los
primeros se matriculan
y se desmatriculan, mientras
que los segundos se pueden
desvincular de la universidad.
Ejemplo de asociacin de
pesos en las interrelaciones
El alumno puede evaluar a su
tutor y esta puntuacin sera la
etiqueta de la relacin.
FUOC P01/75001/00075 25 Tipos abstractos de datos
Como cambios importantes, aparte de la modificacin de la interfaz de la
operacin aade para incorporar las etiquetas, vemos que hay que aadir
una operacin de consulta de la etiqueta asociada a una interrelacin exis-
tente, y tambin la modificacin del resultado de la operacin de consulta de
los recorridos, para que no slo retorne un elemento del dominio que le corres-
ponda, sino tambin la etiqueta asociada (ste es el papel de la clase ElemYElem-
Sum). Este requisito resulta imprescindible para obtener un TAD suficientemente
verstil y adaptable a los algoritmos que lo usarn.
3) Las relaciones pueden ser simtricas. Es decir, el orden de los elementos in-
terrelacionados es irrelevante. Esto nos da nuevas clases en la subjerarqua.
Por ltimo, una especializacin bsica de las relaciones aparece cuando se requie-
re que todos los dominios sean el mismo. El resultado es el TAD de los grafos:
a) En un primer nivel de herencia, obtenemos el TAD de los grafos dirigidos.
Observamos que no se aade ninguna operacin; el nico cambio es la restric-
cin sobre los dominios.
b) Inmediatamente, podemos definir el TAD de los grafos dirigidos etique-
tados, aadiendo las etiquetas y con las modificaciones anteriormente men-
cionadas en este caso.
Ejemplo de grafo
Una red de ordenadores donde
siempre se relacionan pares de
ordenadores es un ejemplo
de grafo.
FUOC P01/75001/00075 26 Tipos abstractos de datos
c) El ltimo TAD que consideraremos es el TAD de los grafos no dirigidos eti-
quetados (el caso no etiquetado no se considera porque no es necesario en esta
asignatura), correspondientes a las relaciones simtricas. Aqu slo hay que re-
cordar la irrelevancia en el orden de los parmetros de las operaciones indivi-
duales sobre las interrelaciones.
En estos TAD sobre grafos, aadimos operaciones que realizan ciertos trabajos es-
pecficos: bsqueda de caminos mnimos (en grafos dirigidos y etiquetas) y cl-
culo de rboles de expansin minimales (en grafos no dirigidos y etiquetados).
Por lo que se refiere a los recorridos en el caso de los grafos, hay que decir que,
como en el caso de los rboles binarios, existen varias clases, aunque en la asigna-
tura slo veremos un tipo: la ordenacin topolgica que nos asegura que visitamos
todos los elementos del grafo en un orden determinado. Los grafos recorribles se
tendran que definir con la misma estrategia que en el caso de los rboles.
2.3. Traduccin de la jerarqua a Java
Cuando definimos la jerarqua, nos abstuvimos de utilizar el lenguaje de progra-
macin que se usa para implementar. Pensamos que sta es la mejor forma de ac-
tuar, porque nos permite separar el problema del diseo y de la implementacin
Consultad la ordenacin topolgica
de los rboles binarios en el mdulo
Secuencias y rboles de esta asignatura.
FUOC P01/75001/00075 27 Tipos abstractos de datos
de la jerarqua. Sin embargo, ahora es necesario ver cmo se plasma la jerar-
qua en el lenguaje que se usa en la asignatura, el lenguaje Java.
Quiz los dos obstculos ms importantes cuando se lleva a cabo la traduccin
son la ausencia en Java de dos mecanismos de estructuracin que hemos utiliza-
do profusamente: la genericidad y la herencia mltiple. Veamos primero cmo
solucionaremos estas ausencias, y despus hablaremos de otros detalles menos
importantes.
2.3.1. Simulacin de la genericidad
Si bien Java no ofrece la genericidad*, podemos aprovechar el hecho de que todas
las clases Java se consideran herederas de una superclase llamada Object. Enton-
ces, los contenedores se pueden definir sobre valores de clase Object, y el polimor-
fismo y la vinculacin dinmica permiten que en tiempo de ejecucin los Object
puedan tomar cualquier forma y se les puedan aplicar los mtodos adecuados.
La clase Object define unos cuantos mtodos que heredan todas las clases que
intervienen en un programa Java. Destacamos dos: el mtodo Clone para dupli-
car valores, yEquals, que permite comparar dos objetos de la clase. La presencia
de estos dos mtodos nos permite decir que Object es equivalente al parmetro
Elem con el que hemos definido los contenedores bsicos.
Sin embargo, tiene que quedar claro que la solucin que adoptamos presenta
ciertas diferencias con respecto a la genericidad:
1) Se pueden construir contenidos heterogneos donde se mezclen elementos
de varias clases, dado que, por las reglas de control para la correccin del tipo
de la orientacin a objetos, cualquier clase heredera de Object (y todas lo son)
puede entrar en el contenedor.
2) La clase Object no ofrece algunas de las funciones que algunos contenedo-
res necesitan ms adelante. Se podra pensar en la creacin de una subjerar-
qua de Object, pero entonces tambin se podran encontrar problemas por la
ausencia de herencia mltiple.
3) Como su nombre indica, los elementos del contenedor deben ser objetos
de clase, y ste no es el caso habitual de valores de tipos predefinidos. Cuando
stos se quieren usar como instancias de Object, hay que transformar previa-
mente los valores en objetos de las clases respectivas.
2.3.2. Simulacin de la herencia mltiple
Java no soporta la herencia mltiple en las clases, pero no es el nico lenguaje
orientado a objetos que presenta este inconveniente. Afortunadamente, pode-
mos usar las interfaces de Java para simularla.
* C++ y Eiffel son lenguajes OO
que ofrecen genericidad.
Consultad laspeculiaridadesde los
mtodosClone y Equal en el
subapartado 6.3. de este mdulo didctico.
Consultad la diferencia entre los
valores de tipos predefinidos y los
objetos de clase que habis estudiado
en la asignatura Fundamentos de
programacin II.
FUOC P01/75001/00075 28 Tipos abstractos de datos
Recordad que las interfaces son clases en las que todos los mtodos son virtua-
les. Dada esta caracterstica, podemos usar las interfaces como un mecanismo
de Java para implementar clases de especificacin. Es decir, todos los TAD de la
jerarqua que hemos visto en este apartado se traducen como interfaces Java.
Las propiedades importantes de las interfaces son las que mencionamos a con-
tinuacin:
a) Una interfaz puede heredar de ms de una interfaz; es decir, las interfaces
s tienen herencia mltiple.
b) Una clase puede implementar una o ms interfaces. Volveremos a este pun-
to ms adelante.
c) Una clase puede implementar slo parcialmente una o ms interfaces.
d) Una clase slo puede heredar de otra clase, independientemente de si im-
plementa interfaces o no.
En el caso de conflictos de nombres de una clase o interfaz que implementa y/o
hereda de ms de una, la poltica es la siguiente:
si se hereda ms de una vez un smbolo con el mismo nombre y parme-
tros, se consideran iguales;
si se hereda un smbolo con el mismo nombre pero parmetros diferentes,
se consideran diferentes.
El gran inconveniente de usar interfaces es la imposibilidad de definir atribu-
tos o implementar mtodos.
Imposibilidad de definir atributos o implementar mtodos en Java
La interfaz para la clase Contenedor resulta de la siguiente manera:
No se puede definir el atributo tamao, ni implementar los mtodos nbElems ni vaco?,
tal como hemos hecho en la jerarqua mediante restricciones.
La herencia mltiple entre contenedores se ilustra en la clase ContenedorRecorri-
ble, que resulta:
public interface Contenedor {
public boolean vacio?();
public int nbElems();
}
public interface ContenedorRecorrible
extends Contenedor, Iterador {
}
Consultad las interfaces introducidas
en la asignatura Fundamentos
de programacinII.
Consultad la implementacin de ms
de una interfaz para una sola clase en
el apartado 3 de este mdulo didctico.
FUOC P01/75001/00075 29 Tipos abstractos de datos
2.3.3. Otras cuestiones
Aparte de los aspectos enunciados en el subapartado anterior, citemos tam-
bin los siguientes:
1) Las operaciones constructoras deben tener el mismo nombre de la clase; si
hay ms de una, diferirn en el nmero y/o tipo de parmetros. Esto afecta a
todas las operaciones de creacin, crea, que desaparecen en Java.
2) No hay operaciones de destruccin porque la gestin que Java hace de la
memoria dinmica (es decir, del espacio ocupado por los objetos) destruye au-
tomticamente los objetos.
La memoria dinmica se estudia
con detalle en el apartado 6 de este
mdulo didctico.
FUOC P01/75001/00075 30 Tipos abstractos de datos
3. Implementacin de TAD
Una vez se dispone de la signatura de un TAD, es el momento de disear im-
plementaciones adecuadas que posibiliten la participacin activa en la ejecu-
cin de los programas, por medio de la utilizacin de un determinado lenguaje
de programacin (orientado a objetos o imperativo).
Laimplementacin de un TAD consta de tres partes:
1) Primero hay que decidir la representacin del TAD, es decir, la estrategia de
representacin de sus valores. En el contexto en que nos movemos, elegir la re-
presentacin del TAD significa decidir un mtodo de almacenamiento de los ele-
mentos del contenedor y representarlo mediante atributos privados de la clase.
2) A continuacin, hay que establecer las relaciones entre estos atributos me-
diante el invariante de la representacin, que identifica todos los estados
admisibles de los objetos de la clase. El invariante consistir en un predicado
booleano, expresado en lenguaje formal o en lenguaje natural (o mezclando
ambos estilos), y su efecto es puramente documental. Para destacar su nece-
sidad, de ahora en adelante consideramos que el invariante de la representa-
cin forma parte de la representacin misma.
3) Por ltimo, conviene escribir algoritmos que codifiquen cada una de las
operaciones del TAD. Cada algoritmo debe usar los atributos de la clase, tanto
para consultarlos como para modificar su valor, y puede invocar mtodos de
otras clases con las que tiene establecida una relacin de uso.
Como se podr ver a lo largo de la asignatura, dado un TAD no existe una nica
implementacin posible, sino muchas (potencialmente infinitas). Una imple-
mentacin puede adaptarse mejor que las otras en un contexto de utilizacin
del TAD, pero puede llegar a ser inadecuada en otros contextos. Por este motivo,
una librera de componentes verstil tendr que ofrecer varias implementacio-
nes de un mismo TAD, de forma que posibilite el uso eficaz en el mximo n-
mero de contextos posibles.
En la escritura de implementaciones se plasma una notacin algortmica inde-
pendiente del lenguaje de programacin concreto. En este caso, los tipos pre-
definidos, constructores de tipos, expresiones e instrucciones se usan con la
sintaxis que ya conocis de otras asignaturas, con las pequeas modificaciones
de notacin exigidas por el cambio de paradigma de programacin (de impe-
rativo a orientado a objetos). Toda la implementacin se encapsula en una cla-
se, en la que hacemos constar el nombre y la clase que encapsula la definicin
del TAD que se implementa.
El invariante en otros
lenguajes OO
Hay lenguajes, como Eiffel, que
permiten escribir invariantes
que se pueden evaluar opcio-
nalmente en tiempo de ejecu-
cin, durante la depuracin del
programa.
En el apartado 4 de este mdulo
didctico se incidir en el problema
de la evaluacin de las implementaciones,
y en el apartado 5 veris ya unas cuantas
estrategias de implementacin de uso
comn.
Recordad la sintaxis de la notacin
algortmica utilizada en la asignatura
Fundamentos de programacin I.
FUOC P01/75001/00075 31 Tipos abstractos de datos
3.1. Representacin del TAD
En este subapartado veremos con detalle en qu consiste la representacin de
un TAD.
3.1.1. Los atributos del TAD
Como ya hemos dicho, la primera parte del proceso consiste en elegir unos
atributos que permitan representar todos los valores posibles del contenedor.
Por eso, podemos usar todos los tipos predefinidos y constructores de tipo que
pone a nuestro alcance el lenguaje de programacin elegido, que recogemos
en la notacin algortmica.
Recapitulemos aqu el abanico de elementos de este tipo que ponen a nuestro
alcance los lenguajes ms habituales, mencionando su implantacin en Java:
1) El tipo de los booleanos (disponible en Java).
2) Los tipos numricos, concretados en varias clases de nmeros enteros y
reales. En Java disponemos de cuatro tipos de nmeros enteros (byte, short, int
y long) y dos reales (float y double), que difieren en el nmero de bits utilizados
en su representacin.
3) El tipo de los caracteres. En Java se tiene el cdigoUnicode, extensin del ASCII.
4) El tipo de la cadena de caracteres (strings), tambin disponible en Java.
5) El constructor de tipos de los vectores. Todo lenguaje de programacin
ofrece de un forma u otra este constructor, imprescindible para almacenar co-
lecciones de elementos, y tambin lo hace Java, con ciertas peculiaridades des-
critas detalladamente en la asignatura Fundamentos de programacin II.
6) El constructor de tipos de las tuplas, para representar agregaciones de da-
tos. Este constructor, normal en los lenguajes imperativos, desaparece en mu-
chos lenguajes orientados a objetos, especialmente en los llamados lenguajes
OO puros, entre los cuales se encuentra Java. El motivo es que los atributos de
una implementacin se interpretan implcitamente como una tupla. Por mo-
tivos de comodidad conservamos las tuplas en la notacin algortmica utiliza-
da en esta asignatura.
La ausencia de tuplas exige introducir clases auxiliares, como podis compro-
bar en las implementaciones en Java de la jerarqua.
3.1.2. El invariante de la representacin
Una vez elegidos los atributos que permiten representar los valores del TAD,
el siguiente paso consiste en escribir el invariante que identifica los estados v-
lidos en los que se puede encontrar un objeto.
Lostipospredefinidosy constructores
de tipo se han introducido en las
asignaturasFundamentos de programacin
I y Fundamentos de programacin II.
Observacin
Hay unas cuantas construccio-
nes secundarias que no se
presentan aqu, como el tipo
por enumeracin, el tipo
subrango, etc.
Consultad el constructor de tipo
de vectores en la asignatura
Fundamentos de programacin II.
Podis recordar la definicin
de lenguaje puro orientado
a objetos en el material de
Fundamentos deprogramacin II.
Consultad la escritura de
implementacionesen Java en el
subapartado 3.3. de este mdulo didctico.
FUOC P01/75001/00075 32 Tipos abstractos de datos
El invariante de la representacin toma la forma de un predicado booleano
que deja explcitas las relaciones entre estos atributos. Cualquier objeto de la
clase que encapsula el TAD tiene que satisfacer este predicado. Obviamente,
esta exigencia no se mantiene durante la ejecucin de un mtodo, momento
en el que el invariante se puede violar temporalmente mientras el mtodo ac-
ta; pero se exige que cuando se acabe la ejecucin del mtodo, el invariante
se vuelva a cumplir.
Idealmente, el predicado booleano ser una formula en lgica de primer orden
que involucrar a los atributos de la clase implementada y a los mtodos de otras
clases; tambin se usarn expresiones propias de la notacin algortmica y, even-
tualmente, se pueden introducir predicados auxiliares. Ahora bien, dado el carc-
ter documental de esta construccin, tambin es lcito expresar informalmente
todo el invariante o parte del mismo, especialmente en aquellas partes en las que
la notacin lgica es suficientemente densa como para no entenderla.
3.2. Codificacin de las operaciones
Para escribir el cdigo de las operaciones introducidas en la signatura del TAD,
podemos utilizar las instrucciones y expresiones habituales que ya conocis.
Slo hay que destacar que a lo largo de esta asignatura usaremos en ocasiones
un concepto nuevo asociado a las diferentes construcciones iterativas, el con-
cepto de invariante del bucle.
El nombre ya denota una similitud con la nocin deinvariante de representacin
y, efectivamente, esta similitud tiene lugar. As como el invariante de la repre-
sentacin indica las combinaciones de valores vlidos de los atributos de la
clase, el invariante del bucle denota las combinaciones de valores vlidos de
los atributos y objetos auxiliares que intervienen en el bucle.
El invariante de la representacin siempre forma parte implcitamen-
te de la precondicin y postcondicin de toda operacin pblica o pro-
tegida del TAD.
La idea fundamental es que, independientemente de si usamos una no-
tacin formal, semiformal o totalmente informal, una clase de imple-
mentacin siempre debe incluir el invariante de la representacin.
El invariante del bucle es un predicado booleano que se debe cumplir
cuando se empieza y se acaba la ejecucin del bucle, as como justo an-
tes de entrar y salir.
Lgica de primer orden
La lgica de primer orden
permite escribir frmulas con
literales, variables, operadores
variados (negaciones, conjun-
ciones, disyunciones, implica-
ciones y equivalencias) y unos
cuantos cuantificadores (uni-
versal y existencial sobre todo,
pero tambin sumatorios y
el llamado cuantificador de
recuento). Si tenis problemas
con la notacin utilizada, po-
dis consultar los apuntes
Introduccin a la lgica
en el material asociado
de la asignatura.
Consultad las expresiones
e instrucciones habituales de
las asignaturas Fundamentos
de programacin I y Fundamentos
de programacin II.
El invariante del bucle
en otros lenguajes OO
Una vez ms, Eiffel es el
lenguaje comercial que
implementa el concepto
de invariante del bucle
en tiempo de ejecucin.
Otros lenguajes lo pueden
simular mediante construccio-
nes de asercin (instrucciones
que se pueden usar en cualquier
punto de un programa para
comprobar si una condicin
se cumple).
FUOC P01/75001/00075 33 Tipos abstractos de datos
No acaban aqu las similitudes. Tambin en los bucles el invariante tiene prop-
sitos esencialmente documentales, si bien hay algn lenguaje que permite su uso
en tiempo de ejecucin. La sintaxis es la misma que en el invariante de la repre-
sentacin. Y tambin se permite su escritura informal. Ahora bien, a diferencia
de los otros, no siempre escribimos los invariantes de los bucles, sino slo cuan-
do pensamos que aportan informacin til. Esto pasar especialmente en los al-
goritmos de grafos y en algn tipo de rboles, en los que el cdigo tiene cierto
grado de complicacin y se considera que el invariante ayuda a su comprensin.
El otro punto relevante de la notacin algortmica tiene que ver con la encapsula-
cin de las operaciones. Dado el paradigma en el que nos encontramos, las opera-
ciones de la signatura del TAD se encapsulan en mtodos que actan siempre sobre
un objeto; mtodos que eventualmente sern funciones, si retornan algn valor.
Pese a esto, si durante el proceso de codificacin de los mtodos se introduce
alguna operacin auxiliar (privada de clase), se puede elegir entre definirla tam-
bin como mtodo (si acta sobre el objeto completo) o como una funcin o
accin parametrizada desligada de los objetos de clase (si acta sobre un sub-
conjunto de los atributos de la clase), con parmetros de entrada, de salida y de
entrada y salida. Por ejemplo, un mtodo de insercin sobre un contenedor
que tiene un vector como atributo puede utilizar una funcin auxiliar para
comprobar si el valor insertado ya est dentro del vector.
Por ltimo, recordemos que las operaciones tienen una precondicin o post-
condicin que, a veces, y cuando sea relevante, haremos explcitas, especial-
mente por lo que se refiere a la precondicin.
En las implementaciones presentadas en esta asignatura supondremos que
una operacin se llama cuando se cumple su precondicin, de forma que no
se comprobarn explcitamente las condiciones de error y, en consecuencia,
no se usar ningn tipo de mecanismo de excepciones para tratarlas.
3.3. Escritura de implementaciones en Java
Ya hemos comentado que las clases de implementacin en Java toman la forma
de clases que implementan una o ms interfaces. Dentro de la clase incluimos
como atributos privados todos aquellos atributos necesarios para representar el
tipo, que sern de tipo predefinido o de clases construidas por el usuario a par-
tir de los constructores de tipo de Java.
Ya hemos hablado de los tipos predefinidos. Por lo que se refiere a los construc-
tores de tipos, tambin hemos comentado la existencia de vector y la inexisten-
cia de tuplas. Sobre este ltimo punto hablaremos ahora.
Si bien en el primer momento puede parecer que las tuplas no son necesarias,
dado que los atributos de la clase se pueden interpretar como campos de una
Hay que tener presente
que los lenguajes orientados
a objetos puros no permitirn
implementar directamente
funciones y acciones al estilo
imperativo, y se necesitar una
traduccin a mtodo. Incluso
considerando esta traduccin,
permitimos este tipo de accio-
nes y funciones imperativas
dada la simplificacin
resultante del cdigo
en algunas situaciones.
Consultad los tipos predefinidos en
el subapartado 3.1.1. de este
mdulo didctico.
FUOC P01/75001/00075 34 Tipos abstractos de datos
tupla que representa el TAD, en realidad la necesidad aparece cuando conside-
ramos la tpica situacin en que tenemos vectores de tuplas. Si no hay tuplas
en Java, cmo podemos declarar estos vectores?
La solucin consiste en declarar una clase auxiliar, que puede ser interna a la
clase principal, que tenga como atributos los campos de tupla. Esta clase juega
un papel de tupla, y la clase principal puede acceder a sus atributos desde cual-
quier punto.
Ejemplo de vector de tuplas
Aqu tenemos un extracto de una clase que define un vector de tuplas de pares de enteros:
Tambin es importante destacar la existencia de una clase llamada Vector, que
podemos utilizar en las implementaciones de TAD con vectores, que define un
mtodo seguro de trabajo con este constructor de tipos. En concreto, esta clase
permite que el vector crezca durante la ejecucin del programa, si se llena, y
tambin suministra unos cuantos mtodos de inters para manejar los objetos
vectores.
Por lo que se refiere a instrucciones en Java, no es necesario aadir nada ms,
ya que todo lo que podamos decir a partir de ahora ya lo conocis de la asig-
naturaFundamentos de programacin II.
class T implements I {
class Node {
public int x, y;
}
private Node A[];