El TDA lista Una vez definido el marco general en el apartado anterior, podemos definir el TDA lista. Matemáticamente, una lista es una secuencia de cero o más elementos de un tipo determinado (conocido como el tipo_de_elemento). A menudo, se representa una lista como una sucesión de elementos separados por comas: A1, A2, ..., An donde n>=0 cada Ai es del tipo tipo_de_elemento A1 es el primer elemento de la lista An es el último elemento de la lista Si n=0 se tiene una lista vacía, es decir, no tiene elementos El TDA lista deriva de la noción matemática de lista, más una definición de operaciones sobre la misma. Típicamente, las operaciones sobre un TDA lista suelen ser: insertar elemento, eliminar elemento, localizar elemento, anular lista, etcétera. No entraremos en el detalle de la implementación las operaciones. La realización de los TDA lista, es posible mediante asignación de memoria estática, como vectores (arrays), o mediante la asignación de memoria dinámica y punteros. El primer método es limitado, por la dificultad del crecimiento de la lista en memoria. Es más frecuente la representación de los TDA lista mediante punteros y la manipulación de su espacio en memoria dinámicamente. La concepción más sencilla de una lista, es la conocida como lista simplemente enlazada, la lista está formada por celdas, cada celda contiene un elemento de la lista y un puntero a la siguiente celda. De esta forma si la lista es A1, A2, ..., An, la celda que contiene Ai tiene un puntero que apunta a la dirección de la celda que contiene a Ai+1, para i=1, 2, ...., n-1. La celda que contiene a An, su puntero está asignado a NULL. Existe también una celda de encabezamiento que apunta a la celda que contiene a A1, esta celda de encabezamiento no tiene ningún elemento. En el caso especial de una lista vacía, el puntero de la celda de encabezamiento apunta a NULL. En C, la estructura que representa la celda, de una lista que almacena enteros podría ser: struct celda { int dato; struct celda *siguiente; }; Una pequeña adición al modelo de lista anterior permitirá aumentar la eficiencia en las manipulaciones de la lista, es la lista doblemente enlazada. La modificación consiste en añadir un puntero que enlace también al elemento anterior de la lista. Así, tendremos cada celda comunicada por un puntero a la celda siguiente y a la celda anterior. Que una lista tenga dos enlaces en lugar de uno, por cada celda, tiene grandes ventajas. Quizá la más importante es que la lista se puede recorrer en cualquier dirección dado cualquier elemento de la lista. Dado un elemento cualquiera de la lista, se puede determinar con rapidez el siguiente y el anterior, esto facilita la administración de la lista en gran medida. Un ejemplo de implementación de celda podría ser: struct celda { int dato; struct celda *siguiente; struct celda *anterior; }; Para terminar con nuestro repaso teórico, vamos a describir dos tipos especiales del tipo fundamental lista: las pilas y las colas. Son tipos de datos lista con una semántica especial. El TDA pila, es un tipo especial de lista en la que todas las inserciones y supresiones tienen lugar en un extremo denominado tope. A las pilas se les denomina también listas LIFO (last in first out), o listas ultimo en entrar primero en salir. El modelo intuitivo de una pila es precisamente una pila de monedas puestas sobre la mesa, o de libros, o de platos sobre una estantería, situaciones todas en las que sólo es conveniente quitar o agregar un objeto del extremo superior de la pila. Tradicionalmente, las dos operaciones básicas (almacenamiento y recuperación) de la pila se llaman push y pop, respectivamente. El TDA cola, es otro tipo especial de lista en la cual los elementos se insertan en uno de sus extremos (el posterior) y se suprimen en el otro (el anterior o frente). Las colas se conocen también como listas FIFO (first-in, first-out) o listas primero en entrar, primero en salir. Las operaciones para una cola, son análogas a una pila; las diferencias sustanciales consisten en que las inserciones se hacen al final de la lista, y no al principio. La analogía con la vida real es la habitual cola de personas en una linea de cajas de un supermercado, o en un cajero de un banco. El primero en llegar es el primero que es servido y se va de la cola, el segundo en llegar es el segundo en ser servido, y así sucesivamente.