Sie sind auf Seite 1von 17

Si profundizamos ms al mundo de la programacin y sus conceptos, existen dos de estos

conceptos que no se deben confundir, ellos son: tipo de datos y estructura de datos.
Un tipo de dato, en un lenguaje de programacin, define un conjunto de valores que una
determinada variable puede tomar, as como las operaciones bsicas sobre dicho conjunto.
Ahora veamos como se van relacionando estos conceptos. Los tipos de datos constituyen un
primer nivel de abstraccin, ya que no se tiene en cuenta cmo se implementan o se
representan realmente la informacin sobre la memoria de la mquina. Para el usuario, el
proceso de implementacin o representacin es invisible.

Origen
El concepto de tipo de dato abstracto (TDA, Abstract Data Type), fue propuesto por primera
vez hacia 1974 por John Guttag y otros, pero no fue hasta 1975 que por primera vez Liskov lo
propuso para el lenguaje CLU.
El lenguaje Turbo Pascal fue determinante para la comn aceptacin de los TDA (Tipo de Dato
Abstracto) con la introduccin de las Units, si bien estas no cumplen con las caractersticas
bsicas de un tipo de dato abstracto como por ejemplo la encapsulacin de los datos. El
lenguaje de programacin denominado Ada. Ada pudo implementar exitosamente los TDA
con sus packages.

Definicin de datos abstractos


Un tipo de datos definido por el programador se le va a conocer como tipo abstracto de datos
(TAD) para distinguirlo de los tipos predefinidos de datos.
Estos son aquellos tipos abstractos de datos los cuales estn formados por los datos (estructuras
de datos) y las operaciones (procedimientos o funciones) que se realizan sobre esos datos. O
podemos definir como tipo de dato abstracto (TDA) o tipo abstracto de datos (TAD) es un
modelo matemtico compuesto por una coleccin de operaciones definidas sobre un conjunto
de datos para el modelo. Tambin podemos mencionar que un TAD o tipo de dato
abstracto es aquel tipo de dato definido por el programador que se puede
manipular de un modo similar a los tipos de datos definidos por el sistema. Y este
se encuentra formado por un conjunto vlido de elementos y un nmero de
operaciones primitivas que se pueden realizar sobre ellos.
Y no hay que olvidar mencionar que el conjunto de operaciones definidas sobre el TAD debe ser
cerrado, es decir, slo se debe acceder a los datos mediante las operaciones abstractas definidas
sobre ellos. La abstraccin de datos slo permite acceder a ellos de manera controlada.

La abstraccin de datos es la caracterstica de un sistema de bases de datos, que permite al


usuario o programador operar con los datos sin necesidad de conocer detalles que para l no
son de importancia, ofreciendo as una visin abstracta de estos.
Para cumplir con tal fin se han definido diferentes niveles de abstraccin: 1

Nivel Fsico. Determina como estn almacenados fsicamente los datos (pistas,
sectores, cilindros), representa el nivel ms bajo.
Nivel Lgico o Conceptual. Determina la organizacin de los archivos. ndices, llaves,
orden de campos, relaciones, tipos de datos.

Nivel de Vistas. Oculta parte de la informacin a los usuarios, es decir hace visible solo
una parte de la base de datos.
Un TDA representa una abstraccin:

Se destacan los detalles (normalmente pocos) de la especificacin (el qu).

Se ocultan los detalles (casi siempre numerosos) de la implementacin (el cmo).


Luego de especificar qu es lo que representa la abstraccin vamos a expresar los diferentes
tipos de abstraccin que podemos encontrar en un programa:
1. Abstraccin funcional: crear procedimientos y funciones e invocarlos mediante un nombre
donde se destaca qu hace la funcin y se ignora cmo lo hace. El usuario solo necesita
conocer la especificacin de la abstraccin (el qu) y puede ignorar el resto de los detalles (el
cmo).
2. Abstraccin de datos:

Tipo de datos: proporcionado por los leguajes de alto nivel. La representacin usada
es invisible al programador, al cual solo se le permite ver las operaciones predefinidas
para cada tipo.

Tipos definidos: por el programador que posibilitan la definicin de valores de datos


ms cercanos al problema que se pretende resolver.

TDA: para la definicin y representacin de tipos de datos (valores + operaciones),


junto con sus propiedades.

Objetos: Son TDA a los que se aade propiedades de reutilizacin y de comparticin


de cdigo.

Estructuras

Las estructuras de los TAD se componen de dos partes: la interfaz y la implementacin. Esto se
debe a que las estructuras de datos reales que utilizamos para almacenar la representacin de un
tipo abstracto de datos son invisibles para los usuarios o clientes. Mientras que en la interfaz se
declaran las operaciones y los datos, y en el caso de la implementacin va a contener el cdigo
fuente de las operaciones y lo mantiene oculto al usuario.

Implementacin
Una vez definido el TAD se escoge una representacin interna utilizando los
tipos que proporciona el lenguaje y / o otros TAD ya definidos previamente.
La representacin deber ocultarse utilizando los mecanismos que nos
proporcione el lenguaje. Ocultamiento de Informacin.
Normalmente la implementacin del tipo se realiza en un mdulo aparte que
ser enlazado al programa principal
Caracterizacin

Un TDA est caracterizado por un conjunto de operaciones (funciones) al cual se


denomina usualmente como interfaz pblica y representa el comportamiento del TDA;
mientras que la implementacin como la parte privada del TDA est oculta al programa
cliente que lo usa. Todos los lenguajes de alto nivel tienen predefinidos TDA; que son
los tipos denominados simples y las estructuras predefinidas, y estos tienen sus
interfaces pblicas que incluyen las operaciones como la +, -, *, etc. no se necesita
conocer cmo actan tales operadores sobre la representacin interna de los tipos
definidos, que adems, suele ser una implementacin bastante dependiente de la
mquina sobre la que trabaje el compilador. Lo interesante es que los lenguajes
actuales nos van a permitir ampliar los TDA predefinidos con otros que sern
definidos por el propio programador para adecuar as los tipos de datos a las
necesidades de los programas.

Los TDA que nos van a interesar de ahora en adelante son aquellos que reflejen cierto
comportamiento organizando cierta variedad de datos estructuradamente. A esta
forma estructurada de almacenar los datos ser a la que nos refiramos para
caracterizar cada TDA.
Los TDA que tienen informaciones simples pero dependientes de un comportamiento
estructural sern llamados polticos y aquellos TDA simples, como son los tipos
predefinidos donde la informacin no es relacionada mediante ninguna estructura y no
admiten ms que un valor en cada momento ser denominados TDA monolticos.
Ntese que cuando hablemos de un TDA no haremos ninguna alusin al tipo de los
elementos sino tan solo a la forma en que estn dispuestos estos elementos. Solo nos
interesa la estructura que soporta la informacin y sus operaciones. Para determinar
el comportamiento estructural basta con observar la conducta que seguirn los datos.
Caractericemos entonces los TDA. Un TDA tendr una parte que ser invisible al
usuario la cual hay que proteger y que se puede decir que es irrelevante para el uso
del usuario y est constituida tanto por la maquinaria algortmica que implemente la
semntica de las operaciones como por los datos que sirvan de enlace entre los
elementos del TDA, es decir, informacin interna necesaria para la implementacin
que se est haciendo para ese comportamiento del TDA. Resumiendo podemos decir,
que tanto la implementacin de las operaciones como los elementos internos del TDA
sern privados al acceso externo y ocultos a cualquier otro nivel.
VENTAJAS
Las principales ventajas que nos aportan los TAD son las siguientes:
1. Mejoran la conceptualizacin y hacen ms claro y comprensible el cdigo.
2. Hacen que el sistema sea ms robusto.
3. Reducen el tiempo de compilacin.
4. Permiten modificar la implementacin sin que afecte al interfaz pblico.
5. Facilitan la extensibilidad.

Tipos de datos abstractos

TDA lista
Una lista se define como una serie de N elementos E1, E2, ..., EN, ordenados de manera
consecutiva, es decir, el elemento Ek (que se denomina elemento k-simo) es previo al
elemento Ek+1. Si la lista contiene 0 elementos se denomina como lista vaca. Las
operaciones que se pueden realizar en la lista son: insertar un elemento en la
posicin k, borrar el k-simo elemento, buscar un elemento dentro de la lista y
preguntar si la lista esta vaca.

Una manera simple de implementar una lista es utilizando un arreglo. Sin embargo, las
operaciones de insercin y borrado de elementos en arreglos son ineficientes, puesto
que para insertar un elemento en la parte media del arreglo es necesario mover todos
los elementos que se encuentren delante de l, para hacer espacio, y al borrar un
elemento es necesario mover todos los elementos para ocupar el espacio desocupado.
Una implementacin ms eficiente del TDA se logra utilizando listas enlazadas.

Ahora se mostrara como se presenta una implementacin en Java del TDA utilizando
listas enlazadas y sus operaciones asociadas:

Lista Vaca (): devuelve verdadero si la lista est vaca, falso en caso
contrario.

insertar(x, k): inserta el elemento x en la k-sima posicin de la lista.

buscar(x): devuelve la posicin en la lista del elemento x.

buscar (k): devuelve el k-simo elemento de la lista.

eliminar(x): elimina de la lista el elemento x.

En la implementacin con listas enlazadas es necesario tener en cuenta algunos


detalles importantes: si solamente se dispone de la referencia al primer elemento, el
aadir o remover en la primera posicin es un caso especial, puesto que la referencia a
la lista enlazada debe modificarse segn la operacin realizada. Adems, para eliminar
un elemento en particular es necesario conocer el elemento que lo antecede, y en este
caso, qu pasa con el primer elemento, que no tiene un predecesor?

Para solucionar estos inconvenientes se utiliza la implementacin de lista enlazada con


nodo cabecera. Con esto, todos los elementos de la lista tendrn un elemento previo,
puesto que el previo del primer elemento es la cabecera. Una lista vaca corresponde,
en este caso, a una cabecera cuya referencia siguiente es null.

Los archivos NodoLista.java, IteradorLista.java y Lista.java contienen una


implementacin completa del TDA lista. La clase Nodo Lista implementa los nodos de
la lista enlazada, la clase Lista implementa las operaciones de la lista propiamente tal,
y la clase Iterador Lista implementa objetos que permiten recorrer la lista y posee la
siguiente interfaz:

avanzar (): avanza el Iterador al siguiente nodo de la lista.

obtener (): retorna el elemento del nodo en donde se encuentra el Iterador.

Costo de las operaciones en tiempo:

Insertar/eliminar elemento en k-sima posicin: O(k) (Se puede hacer


en O(1)?).

Buscar elemento x: O(N) (promedio).

TDA pila
Una pila (stack o pushdown en ingls) es una lista de elementos de la cual slo se puede
extraer el ltimo elemento insertado. La posicin en donde se encuentra dicho
elemento se denomina tope de la pila. Tambin se conoce a las pilas como listas
LIFO (LAST IN - FIRST OUT: el ltimo que entra es el primero que sale).
La interfaz de este TDA provee las siguientes operaciones:

apilar(x): inserta el elemento x en el tope de la pila (push en ingls).

desapilar (): retorna el elemento que se encuentre en el tope de la pila y lo


elimina de sta (pop en ingls).

tope (): retorna el elemento que se encuentre en el tope de la pila, pero sin
eliminarlo de sta (top en ingls).

est Vaca (): retorna verdadero si la pila no contiene elementos, falso en caso
contrario (is Empty en ingls).

Tambin podemos definir desapilar como sacar el elemento del tope de la pila sin
retornarlo.

Implementacin del TDA pila


Ahora explicaremos dos maneras de implementar una pila: utilizando un arreglo y
utilizando una lista enlazada. En ambos casos el costo de las operaciones es de O (1).

Implementacin utilizando arreglos


Para implementar una pila utilizando un arreglo, basta con definir el arreglo del tipo de
dato que se almacenar en la pila. Una variable de instancia indicar la posicin del
tope de la pila, lo cual permitir realizar las operaciones de insercin y borrado, y
tambin permitir saber si la pila est vaca, definiendo que dicha variable vale -
1 cuando no hay elementos en el arreglo.
Class PilaArreglo
{
Private Object [] arreglo;
Prvate int tope;
Prvate int MAX_ELEM=100; // mximo nmero de elementos en la pila

Public PilaArreglo ()
{
Arreglo=new Object [MAX_ELEM];
Tope=-1; // inicialmente la pila est vaca
}

Public void apilar (Object x)


{
If (tope+1<MAX_ELEM) // si est llena se produce OVERFLOW
{
Tope++;
Arreglo [tope]=x;
}
}

Public Object desapilar ()


{
If (!estaVacia()) // si esta vaca se produce UNDERFLOW
{
Object x=arreglo [tope];
Tope--;
Return x;
}
}

Public Object tope ()


{
If (!estaVacia()) // si esta vaca es un error
{
Object x=arreglo [tope];
Return x;
}
}

Public Boolean estaVacia ()


{
If (tope==-1)
{
Return true;
}
Else
{
Return false;
}
}
}
El inconveniente de esta implementacin es que es necesario fijar de antemano el
nmero mximo de elementos que puede contener la pila, MAX_ELEM, y por lo tanto al
apilar un elemento es necesario controlar que no se inserte un elemento si la pila est
llena. Sin embargo, en Java es posible solucionar este problema creando un nuevo
arreglo ms grande que el anterior, el doble por ejemplo, y copiando los elementos de
un arreglo a otro:

Public void apilar (Object x)


{
If (tope+1<MAX_ELEM) // si est llena se produce OVERFLOW
{
Tope++;
Arreglo [tope] =x;
}
Else
{
MAX_ELEM=MAX_ELEM*2;
Object [] nuevo_arreglo=new Object [MAX_ELEM];
For (int i=0; i<arreglo. Length; i++)
{
nuevo_arreglo[i]=arreglo[i];
}
Tope++;
Nuevo arreglo [tope]=x;
Arreglo=nuevo arreglo;
}
}

Implementacin utilizando listas enlazadas


En este caso no existe el problema de tener que fijar el tamao mximo de la pila
(aunque siempre se est acotado por la cantidad de memoria disponible!). La
implementacin es bastante simple: los elementos siempre se insertan al principio de
la lista (apilar) y siempre se extrae el primer elemento de la lista (desapilar y tope),
por lo que basta con tener una referencia al principio de la lista enlazada. Si dicha
referencia es null, entonces la pila est vaca.

Class PilaLista
{
Prvate Nodo Lista;

Public PilaLista ()
{
Lista=null;
}

Public void apilar (Object x)


{
Lista=new Nodo Lista(x, lista);
}

Public Object desapilar () // si esta vaca se produce UNDERFLOW


{
If (! estaVacia ())
{
Object x=lista.elemento;
Lista=lista. Siguiente;
Return x;
}
}

Public Object tope ()


{
If (!estaVacia()) // si esta vaca es un error
{
Object x=lista.elemento;
Return x;
}
}

Public boolean estaVacia ()


{
Return lista==null;
}
}
Dependiendo de la aplicacin que se le d a la pila es necesario definir que accin
realizar en caso de que ocurra overflow (rebalse de la pila) o underflow (intentar
desapilar cuando la pila est vaca). Java posee un mecanismo denominado excepciones,
que permite realizar acciones cuando se producen ciertos eventos especficos (como
por ejemplo overflow o underflowen una pila).En ambas implementaciones el costo de
las operaciones que provee el TDA tiene costo O (1).

Ejemplo de uso: eliminacin de recursividad


Suponga que una funcin F realiza un llamado recursivo dentro de su cdigo, lo que se
ilustra en la siguiente figura:

Si la llamada recursiva es lo ltimo que hace la funcin F, entonces dicha llamada se


puede substituir por un ciclo while. Este caso es conocido como tail recursin y en lo
posible hay que evitarlo en la programacin, ya que cada llamada recursiva ocupa
espacio en la memoria del computador, y en el caso del tail recursin es muy simple
eliminarla. Por ejemplo:

Void imprimir (int [] a, int j) // versin recursiva


{
If (j<a.length)
{
System.out.print (a[j]);
Imprimir (a, j+1); // tail recursion
}
}
Void imprimir (int [] a, int j) // version iterative
{
While (j<a.length)
{
System.out.print (a[j]);
j=j+1;
}
}
En el caso general, cuando el llamado recursivo se realiza en medio de la funcin F, la
recursin se puede eliminar utilizando una pila.
Por ejemplo: recorrido en preorden de un rbol binario.

// "raz" es la referencia a la raz del rbol


// Llamado inicial: preorden (raz)

// Versin recursiva

Void preorden (Nodo nodo)


{
If (nodo! =null)
{
System.out.print (nodo.elemento);
Pre orden (nodo.izq);
Pre orden (nodo.der);
}
}
// Primera versin iterativa
Void pre orden (Nodo nodo)
{
Nodo aux;
Pila pila=new Pila (); // pila de nodos
Pila. Apilar (nodo);
While (!pila. EstaVacia ()) // mientras la pila no este vaca
{
Aux=pila.desapilar ();
If (aux! =null)
{
System.out.print (aux.elemento);
// Primero se apila el nodo derecho y luego el izquierdo
// Para mantener el orden correcto del recorrido
// Al desapilar los nodos
Pila. Apilar (aux.der);
Pila. Apilar (aux.izq);
}
}
}
// Segunda versin iterativa
// Dado que siempre el ultimo nodo apilado dentro del bloque if es
// aux.izq podemos asignarlo directamente a aux hasta que ste sea
// Null, es decir, el bloque if se convierte en un bloque while
// y se cambia el segundo apilar por una asignacin de la referencia

Void pre orden (Nodo nodo)


{
Nodo aux;
Pila pila=new Pila (); // pila de nodos
Pila. Apilar (nodo);
While (!pila. EstaVacia ()) // mientras la pila no este vaca
{
Aux=pila.desapilar ();
While (aux! =null)
{
System.out.print (aux.elemento);
Pila. Apilar (aux.der);
Aux=aux.izq;
}
}
}
Si bien los programas no recursivos son ms eficientes que los recursivos, la
eliminacin de recursividad (excepto en el caso de tail recursin) le quita claridad al
cdigo del programa. Por lo tanto:

A menudo es conveniente eliminar el tail recursin o cola de recursin.

Un mtodo recursivo es menos eficiente que uno no recursivo, pero slo en


pocas oportunidades vale la pena eliminar la recursin.

TDA cola
Una cola es una lista de elementos en donde siempre se insertan nuevos elementos al
final de la lista y se extraen elementos desde el inicio de la lista. Tambin se conoce a
las colas como listas FIFO (FIRST IN - FIRST OUT: el primero que entra es el
primero que sale).
Las operaciones bsicas en una cola son:

encolar(x): inserta el elemento x al final de la cola.

sacar (): retorna el elemento que se ubica al inicio de la cola.

estaVacia (): retorna verdadero si la cola est vaca, falso en caso contrario.

Al igual que con el TDA pila, una cola se puede implementar tanto con arreglos como
con listas enlazadas. A continuacin se ver la implementacin usando un arreglo.Las
variables de instancia necesarias en la implementacin son:

primero: indica el ndice de la posicin del primer elemento de la cola, es decir,


la posicin el elemento a retornar cuando se invoque sacar.

ultimo: indica el ndice de la posicin de ltimo elemento de la cola. Si se


invoca encolar, el elemento debe ser insertado en el casillero siguiente al que
indica la variable.

num_elem: indica cuntos elementos posee la cola.


Definiendo MAX_ELEM como el tamao mximo del arreglo, y por lo tanto de la
cola, entonces la cola est vaca si num_elem==0 y est llena
si num_elem==MAX_ELEM.

Un detalle faltante es el siguiente: qu pasa si la variable ultimo sobrepasa el rango


de ndices del arreglo? Esto se soluciona definiendo que si despus de insertar un
elemento el ndice ultimo == MAX_ELEM, entonces se asigna ultimo = 0 , y los
siguientes elementos sern insertados al comienzo del arreglo. Esto no produce ningn
efecto en la lgica de las operaciones del TDA, pues siempre se saca el elemento
referenciado por el ndice primero, aunque en valor absoluto primero > ultimo. Este
enfoque es conocido como implementacin con arreglo circular, y la forma ms fcil de
implementarlo es haciendo la aritmtica de subndices mdulo MAX_ELEM.

Class ColaArreglo
{
Prvate Object [] arreglo;
Prvate int primero, ultimo, num_elem;
Prvate int MAX_ELEM=100; // mximo nmero de elementos en la cola
Public ColaArreglo ()
{
Arreglo=new Object [MAX_ELEM];
Primero=0;
Ultimo=-1;
num_elem=0;
}
Public void encolar (Object x)
{
If (num_elem<=MAX_ELEM) // si est llena se produce OVERFLOW
{
Ultimo=(ultimo+1)%MAX_ELEM;
Arreglo [ultimo]=x;
Num_elem++;
}
}

Public Object sacar ()


{
If (!estaVacia()) // si esta vaca se produce UNDERFLOW
{
Object x=arreglo [primero];
Primero= (primero+1) %MAX_ELEM;
Num_elem--;
Return x;
}
}
Public Boolean estaVacia ()
{
Return num_elem==0;
}

TDA Cola de Prioridad


Una cola de prioridad es un tipo de datos abstracto que almacena un conjunto de
datos que poseen una llave perteneciente a algn conjunto ordenado, y
permite insertar nuevos elementos y extraer el mximo (o el mnimo, en caso de que la
estructura se organice con un criterio de orden inverso). Es frecuente interpretar los
valores de las llaves como prioridades, con lo cual la estructura permite insertar
elementos de prioridad cualquiera, y extraer el de mejor prioridad.

Dos formas simples de implementar colas de prioridad son:

Una lista ordenada:

o Insercin: O(n)

o Extraccin de mximo: O(1)

Una lista desordenada:

o Insercin: O(1)

Extraccin de mximo: O(n)

Tipos bsicos de operaciones en un TAD

Constructores: Crean una nueva instancia del tipo.


Transformacin: Cambian el valor de uno o ms elementos de una instancia
del tipo.
Observacin: Nos permiten observar el valor de uno o varios elementos de
una instancia sin modificarlos.
Itera dores: Nos permiten procesar todos los componentes en un TDA de
forma secuencial.
TAD:
Operaciones:
Asignaciones.
Incrementos.
Decrementos.
Operaciones aritmticas.

TDA.- estudiante: conjunto de datos


RU [numero];
Nombre [Texto];
Edad [numero];

Operaciones:

Ver nombres ();
Calcular edad();
Modificar edad();
TDA.- Conjuntos: Conjunto de datos

Set [numero texto];

Operaciones:

Unin.
interseccin.
comparacin.

Ejemplos de uso de TDA

Algunos ejemplos del uso de TDA en programacin son:

Conjuntos: implementacin de conjuntos con sus operaciones bsicas (unin,


interseccin y diferencia), operaciones de insercin, borrado, bsqueda...

rboles Binarios de Bsqueda: Implementacin de rboles de elementos,


utilizados para la representacin interna de datos complejos. Aunque siempre se
los toma como un TDA separado son parte de la familia de los grafos.

Pilas y Colas: Implementacin de los algoritmos FIFO y LIFO.

Grafos: Implementacin de grafos; una serie de vrtices unidos mediante una


serie de arcos o aristas.

Das könnte Ihnen auch gefallen