TDA-LISTA

Anuncio
Trabajo Final
TDA-LISTA
Julia de Frutos
Svenja Heydorn
Eduardo Fernández
I.- Definición
1-TDA
Un TDA se puede definir como un modelo matemático con una serie de
operaciones definidas en ese modelo. Como propiedades fundamentales que
proporcionan podemos destacar la generalización y la encapsulación. En
general los TDA son los tipos de datos primitivos (enteros, caracteres, ...),
al igual que las operaciones para operarlos, que son generalizaciones de
operaciones primitivas (suma, resta, etcétera). Cuando dice que encapsula
cierto tipo de datos se refiere a que gracias a ellos, es posible localizar la
definición del tipo y además, todas las operaciones con ese tipo se pueden
localizar en una sección del programa. Por lo tanto, si se desea cambiar la
forma de implementar un TDA, se puede realizar sin perder la semántica del
mismo
y
en
alguna
zona
del
código
muy
concreta.
Más concretamente, los TDA están representados por estructuras de datos
conectadas entre sí, manipulados con operaciones sobre esas estructuras.
2-TDA-lista
En general, una lista es una secuencia de elementos de la forma: a1, ... ,an,
donde n>=0, y cada elemento ai es de tipo genérico. El tamaño de la lista
es n, pero si n=0, se dice que la lista es vacía. Para todas las listas, menos
esta última, el primer elemento es a1 y el último elemento es an. Se dice
que ai+1 es sucesor de ai (i<n) y que ai-1 es predecesor de ai (i>1). Por lo
tanto, los elementos pueden estar ordenados en función de su posición (i en
el caso de ai).
A diferencia de los conjuntos puede haber elementos repetidos en la lista, y
a diferencia de las matrices y registros, el numero de elementos de la lista
no es fijo, es variable y por lo tanto, no está limitado desde el principio.
En una máquina de información cada elemento suele denominarse nodo
(celda o caja) que puede contener uno o más punteros.
Las listas admiten una serie de operaciones, que podemos agrupar en
operaciones de construcción(crear), operaciones de posicionamiento(fin,
primero, siguiente, anterior), operaciones de consulta(vacía, longitud) y
finalmente operaciones de modificación(modificar, borrar, insertar), que se
detallarán e implementarán más adelante.
Los TDA-lista se pueden realizar mediante memoria estática(vectores o
arrays), o mediante asignación de memoria dinámica y punteros.
Cuando se procesan conjuntos de datos cuyo espacio de almacenamiento no
se puede predecir a priori ( en tiempo de compilación) y además la
actividad de los mismos (inserciones y borrados) es frecuente, las
estructuras de datos estáticas (los arrays) no son adecuadas para su
implementación. Las razones son varias:
1
Trabajo Final
Julia de Frutos
Svenja Heydorn
Eduardo Fernández
1. Los arrays deben ser declarados en tamaño en el programa fuente,
de modo que si se elige uno mayor que el necesario, entonces se
desperdicia espacio de memoria.
2. La operación de añadir datos al final de la lista (el arrays) es un
proceso rápido; sin embargo, las inserciones y eliminaciones en el
interior del array son lentas y complejas, ya que puede ser necesario
desplazar cada elemento del array para hacer espacio al nuevo
elemento, o bien cerrar el espacio dejado por una eliminación.
Pese a esto, nos podemos encontrar fácilmente con las listas mas sencillas
realizadas mediante vectores. En la primera posición encontramos el
número de elementos de la lista y en las demás los elementos en sí. Un
ejemplo es:
4
l
alpha
beta
gamma
delta
Las listas son unas estructuras de datos muy útiles para los casos en los
que se necesita almacenar información de la que no se conoce su tamaño
con antelación. También son valiosas para las situaciones en las que el
volumen de datos se puede incrementar o decrementar dinámicamente
durante la ejecución del programa, como ya hemos dicho.
Por lo tanto, usando punteros y memoria dinámica podemos encontrar las
listas simplemente enlazadas, retratadas a continuación.
Estas listas poseen nodos o registros que contienen el elemento
correspondiente a su posición en la lista y un puntero al siguiente nodo que
contiene su sucesor. Es el puntero llamado “siguiente”. Claro está, el
puntero siguiente de la última celda apunta a nil. En el caso de existir una
celda llamada cabeza o encabezamiento, ésta contiene la longitud de la lista
en ese momento y un puntero que apunta al primer nodo. En las listas que
hemos visto en clase la cabecera tiene un puntero más que apunta al último
nodo. Es importante recordar que el puntero no es más que una variable
que contiene la dirección dónde está almacenado otro dato.
Existe otro modelo de lista que mejora la eficiencia respecto al modelo
anterior. Se trata de las listas doblemente enlazadas. Es de utilidad cuando
se quiere recorrer la lista hacia atrás. Hay que añadir un puntero más, en
cada celda de modo que se apunta al nodo anterior.
2
Trabajo Final
Julia de Frutos
Svenja Heydorn
Eduardo Fernández
Estos nuevos punteros van a duplicar el costo de las inserciones y
eliminaciones por el hecho de manejar más punteros, pero por otro lado se
simplifican las eliminaciones al no tener que llamar al nodo anterior. Un tipo
común y particular de este tipo de listas son las listas enlazadas
circularmente. Se pueden hacer con cabecera o sin ella. En ellas, el
apuntador anterior del primer nodo apunta al ultimo nodo. Un ejemplo es:
Ya hemos apuntado algunas ventajas u inconvenientes con respecto a usar
en las implementaciones de listas vectores o listas enlazadas. Añadimos , a
continuación algunas en cuanto al coste de las operaciones.
Con vectores:
Algunas de coste O(1): crear_lista(), borrar_lista(),tamaño(), vacía? (),
llena? (),final? (), siguiente(),primero(), ultimo(), contenido()
Otras operaciones y sus costes: buscar()-O(n/2) o O(log(n));
recorrer_lista()-O(n); insertar(),eliminar()-O(n + log(n))
Con listas enlazadas:
Coste O(1): crear_lista(), borrar_lista(),tamaño(), vacía? (),
llena? (),final? (), siguiente(),primero(), ultimo(), contenido()
Otras
operaciones
y
sus
costes:
buscar(),
anterior(),insertar(),eliminar()-O(n/2); recorrer_lista()-O(n).
3
Trabajo Final
II.- Ejemplos
Julia de Frutos
Svenja Heydorn
Eduardo Fernández
En el campo de la informática son numerosos los ejemplos en los que
usamos listas enlazadas. A continuación, se muestran dos de ellos.
El primero es el llamado polinomio TDA, en el que se define un tipo de dato
abstracto para polinomios de una variable, con coeficientes ai. Se trata de
almacenar los coeficientes en la lista de modo que se puedan efectuar con
facilidad las operaciones suma, multiplicación...
Otro ejemplo mas complicado tiene lugar cuando se quiere realizar informes
en una universidad por ejemplo de 40000 estudiantes y 2500 cursos, sobre
el numero de matriculados en cada clase y las clases en las que está
inscrito cada alumno. Necesitamos una lista por clase que contenga cada
estudiante y una lista por estudiante que contenga las clases que cursa. Un
ejemplo de implementación sería con dos listas combinadas en una. Es decir
todas las listas son circulares y a la vez tienen cabecera llamada Ci en
función de la clase y Ei en función del alumno.
Como ejemplo partimos de la clase C3 y vamos a recorrer su lista. El primer
nodo corresponde a un estudiante, si recorremos a su vez esta lista del
estudiante hasta llegar a la cabecera conoceremos al estudiante E4. A
continuación, regresamos a la lista de clase C3 (dónde habíamos guardado
la posición en la que nos habíamos quedado) y pasamos a la siguiente
celda, que pertenecerá a E5. Y así podemos continuar de manera que
conozcamos en cuantas clases está matriculado cada alumno.
4
Trabajo Final
Julia de Frutos
Svenja Heydorn
Eduardo Fernández
III.- Operaciones del TDA lista
Aquí se muestran las cabeceras de todas y cada una de las operaciones del
TDA lista en C utilizando vectores.
1- Declaración de tipos
#define TAM 1000
typedef T elemento;
typedef int posicion;
typedef struct{
int longitud;
elemento info[Tam];
} Lista;
typedef int logico;
T es el tipo de dato que nosotros tenemos. Puede ser entero, caracter,
lógico o cualquier otra estructura que se nos ocurra.
2- Operaciones elementales
Independientes de la implementación
logico vacia(Lista *L){
}
logico llena(Lista *L){
}
A la variable tam se le asigna el tamaño de la lista (L.longiutd). Si bien no
es necesaria ya que podemos utilizar la función tamaño en su lugar, porque
nos devuelve el tamaño de la lista.
Vacia nos devuelve cierto si la lista está vacia y falso si no lo está.
Llena nos devuelve cierto si la lista está llena y falso si no lo está.
La variable de tipo logico es un entero al implementarlo en C. El valor de
falso en C es 0 y el de cierto 1.
Dependientes de la implementación
logico crear_lista(Lista *L){
}
No de devuelve cierto si la lista se ha creado correctamente
int tamaño(Lista *L){
}
Nos devuelve el tamaño de la lista
logico final(Lista *L, posicion p){
}
Nos devuelve cierto si es el final de la lista
5
Trabajo Final
Julia de Frutos
Svenja Heydorn
Eduardo Fernández
logico contenido(Lista *L, posicion p, elemento *E){
}
Nos devuelve falso si el elemento está junto con lo que vale el elemento E.
Si no está, nos devuelve cierto.
logico primero(Lista *L, posicion *p){
}
Si la lista no está vacia p vale 1 y la función devuelve falso.
logico ultimo(Lista *L, posicion *p){
}
Si la lista no está vacia p vale el tamaño de la lista y la función devuelve
falso.
logico siguiente(Lista *L, posicion p, posicion *q){
}
Si la lista no está vacia y p no es el último, q vale una posiciona mas que p.
Siguiente devuelve falso.
logico anterior(Lista *L, posicion p, posicion *q){
}
Si la lista no está vacia y p no es el primero q guarda una posición que p.
Siguiente devuelve falso.
3- Operaciones no elementales:
Independientes de la implementación
void recorrer_lista(Lista *L){
}
logico buscar(Lista *L, elemento E, posicion *p){
}
Si el elemento E no está p guarda la posición donde debería de estar E y la
función devuelve cierto.
Dependientes de la implementación
logico insertar(Lista *L, elemento E){
}
La función devuelve cierto si no hemos podido insertar correctamente el
elemento E.
logico eliminar(Lista *L, elmento E){
}
La función devuelve cierto si no hemos podido eliminar correctamente el
elemento E.
6
Trabajo Final
IV.- Bibliografía
Julia de Frutos
Svenja Heydorn
Eduardo Fernández
Weiss, "Estructuras de datos y Algoritmos", Addison-Wesley Pub.
Aho, Hopcroft y Ullman. “Estructuras de datos y Algoritmos”. AddisonWesley, 1998.
www.kernel-labs.org
www.itlp.edu.mx/publica/tutors.htm
www.infor.uva.es/~belar/
7
Documentos relacionados
Descargar