Вы находитесь на странице: 1из 4

Estructuras de Datos Lineales

En este tema se estudia la primera gran familia de TADs, todos ellos derivados del concepto de secuencia. Primero se
definen las secuencias como conjuntos de elementos entre los que se establece una relación de predecesor y sucesor.
Los diferentes TADs basados en este concepto se diferenciaran por las operaciones de acceso a los elementos y
manipulación de la estructura. Desde el punto de vista de la informática, existen tres estructuras lineales especialmente
importantes: las pilas, las colas y las listas. Su importancia radica en que son muy frecuentes en los esquemas
algorítmicos.

Las operaciones básicas para dichas estructuras son:

 crear la secuencia vacía


 añadir un elemento a la secuencia
 borrar un elemento a la secuencia
 consultar un elemento de la secuencia
 comprobar si la secuencia está vacía

La diferencia entre las tres estructuras que se estudiarán vendrá dada por la posición del elemento a añadir, borrar y
consultar:

 Pilas: las tres operaciones actúan sobre el final de la secuencia


 Colas: se añade por el final y se borra y consulta por el principio
 Listas: las tres operaciones se realizan sobre una posición privilegiada de la secuencia, la cual puede
desplazarse

Se presenta el TAD de las pilas de elementos arbitrarios. Tras especificarlo, se muestra su implementación en vector
(posteriormente se verá su implementación con memoria dinámica) y se discuten sus ventajas y desventajas.

Después se muestran las colas siguiendo un proceso idéntico al del subtema anterior. Se presenta y discute la
implementación en vector circular (también posteriormente se verá su implementación en memoria dinámica).

Respecto a las listas, dado que hay muchas versiones diferentes se escoge una como base. Concretamente las listas
con punto de interés, donde existe un elemento que sirve de referencia a las operaciones de inserción, supresión y
consulta. Estas listas tienen el interés añadido de que son equivalentes a la noción de secuencia que los estudiantes
conocen de Programación. Se da una especificación formal de estas listas y se discuten las diferentes
implementaciones. Tras considerar una implementación secuencial, que resulta ineficiente en general, se detalla la
representación encadenada, mucho más eficiente (coste constante en todas las operaciones), usando vectores. En la
representación encadenada se ve la utilidad de introducir un elemento fantasma, que evita casos especiales en los
algoritmos y simplifica el código.

Ante el problema de previsión de memoria necesaria a reservar, se presenta la utilización de memoria dinámica. Se
exponen todos los inconvenientes asociados al uso de memoria dinámica (generación de basura, referencias colgadas,
compartición de memoria, etc.) y se ilustran los peligros asociados a las implementaciones que los usan. Se muestra
de forma muy natural la implementación con punteros de las listas, y se recuerdan las pilas y las colas comentando su
implementación dinámica.

Para terminar se presentan algunas variantes de la representación encadenada. En particular las listas circulares y
las listas doblemente encadenadas. Para cada una de ellas se muestra su utilidad en distintos contextos.

4.1 Pilas
4.2 Colas
4.3 Listas con punto de interés
4.4 Memoria dinámica
4.5 Otros tipos de listas
Esta estructura puede compararse con una pila de libros, donde el último en ponerse encima de la pila es el
primero en retirarse de ella, y en general los libros se retiran en el orden inverso a como se han apilado.

A continuación se muestra la especificación formal del tipo Pila

Especificación pila (elemento)

usa booleano

tipo pila
operaciones
crear: -> pila

apilar: pila x elemento -> pila

desapilar: pila -> pila

cima: pila -> elemento


vacía: pila -> booleano
errores
desapilar (crear)
cima (crear)
ecuaciones p  pila,  e  elemento
desapilar (apilar (p, e)) = p

cima (apilar (p, e)) = e

vacía (crear) = cierto


vacía (apilar (p, e)) = falso
Fespecificación
Implementación por vectores

En esta implementación la pila se representa por medio de un vector y un apuntador a la cima del vector.

elems = = tabla [1..MAX] de elemento


pila = = tupla
vector: elems

cima: entero
ftupla
función crear retorna pila
var
p: pila
fvar
p.cima := 0
retorna p
ffuncion

función apilar (ent p: pila, ent e: elemento) retorna pila

si p.cima = MAX entonces


Tratamiento_de_Error
sino
p.cima := p.cima + 1
p.vector [p.cima] := e
fsi
retorna p
ffuncion
Ejercicio: escribir la implementación por medio de vectores del resto de operaciones del TAD pila.

Puede verse fácilmente que que el tiempo de ejecución es de (1) para todas las operaciones, por tanto es
muy eficiente en ejecución, pero tiene el inconveniente de que hay que reservar un máximo de espacio de
memoria para el vector, espacio que en muchos casos no se aprovecha.

Esta estructura puede compararse con la cola del cajero de un supermercado,


donde los clientes son atendidos en el orden de llegada.

A continuación se muestra la especificación formal del tipo Cola

Especificación cola (elemento)

usa booleano

tipo cola
operaciones
crear: -> cola

encolar: cola x elemento -> cola

desencolar: cola -> cola

cabeza: cola -> elemento


vacía: cola -> booleano
errores
desencolar (crear)
cabeza (crear)
ecuaciones c  cola,  e  elemento
desencolar (encolar (crear, e)) = crear

no vacia (c) ==> desencolar (encolar (c, e)) = encolar (desencolar (c, e))

cabeza (encolar (crear, e)) = e

no vacia (c) ==> cabeza (encolar (c, e)) = cabeza (c)

vacía (crear) = cierto


vacía (encolar (c, e)) = falso
Fespecificación

Implementación por vectores

En este tipo de implementación la cola se implementa por medio de un vector circular, es decir a medida que se
añaden y se borran elementos de la cola cuando se llega al final del vector se continua por el principio. Se
utilizan además dos apuntadores, uno que señala la cabeza de la cola y otro que señala el final de ella. Para
evitar confusiones cuando ambos apuntadores señalan a un mismo elemento, no sabiendo si es porque la cola
está vacía o está llena, se añadirá un contador que dirá el número de elementos en la cola.

elems = = tabla [1..MAX] de elemento


cola = = tupla
vector: elems

cab, col, número: entero


ftupla
función crear retorna cola
var
c: cola
fvar
c.cab := 1

c.col := 1

c.numero := 0
retorna p
ffuncion

función encolar (ent c: cola, ent e: elemento) retorna cola

si c.número = MAX entonces


Tratamiento_de_Error
sino
c.vector [c.cola] := e
c.cola := c.cola mod MAX + 1 {recorre circularmente la secuencia de números
1, 2, ..., MAX, 1, 2, ...}
c. número := c.número + 1
fsi
retorna p
ffuncion
Ejercicio: escribir la implementación por medio de vectores del resto de operaciones del TAD cola.

Puede verse fácilmente que que el tiempo de ejecución de las operaciones es de (1), por tanto es muy
eficiente en ejecución, pero tiene el inconveniente de que hay que reservar un máximo de espacio de memoria
para el vector, espacio que en muchos casos no se aprovecha.