Estructura de datos - Unidad 1: Introducción a las estructuras de datos
Estructuras de datos_dinamicas_definicion_e_implementacion_
1. Estructuras Dinámicas de Datos. Listas Pilas y Colas Tema 2.
TEMA 2: ESTRUCTURAS DINÁMICAS DE DATOS. LISTAS, PILAS Y COLAS
1. Tipos Abstractos de Datos.
2. Estructuras Dinámicas de Datos.
3. Representación y manipulación de Listas.
4. Concepto e implementación de Pilas.
5. Concepto e implementación de Colas.
TEMA 2. ESTRUCTURAS DINAMICAS DE DATOS.
LISTAS, PILAS Y COLAS.
1. Tipos abstractos de Datos.
La objetivo fundamental de la introducción del concepto de tipo abstracto de
datos es la de poder separar la representación de los datos del uso de esos datos. Para
empezar, hay que precisar la diferencia entre tres conceptos muy relacionados pero
formalmente distintos aunque sea corriente utilizar el mismo nombre para casos
concretos y muy importantes. Se trata de los conceptos de “Tipo de Datos”, “Tipo
abstracto de Datos” y “Estructura de Datos”. Las definiciones se pueden establecer de la
siguiente forma:
• Un Tipo de Datos (TD) es el conjunto de valores que puede tomar una variable.
• Un Tipo Abstracto de Datos (TAD) es un modelo matemático compuesto por un
tipo de datos (TD) y las operaciones que se pueden realizar con ellos.
• Una Estructura de Datos (ED) es la representación o implementación de un tipo
abstracto de datos (TAD) mediante un conjunto de variables “conectadas”.
Hay que tener en cuenta, por un lado, que un tipo consta no sólo de los valores
que puede tomar, sino también de las operaciones posibles sobre ellos. Las operaciones
son básicamente de tres tipos: Constructores, Modificadores y Manipuladores.
Tendremos, por un lado la representación de los datos mediante unas estructuras de
datos determinadas establecidas en términos de otros tipos de datos básicos o ya
establecidos y, por otro, la implementación sobre esta representación de las operaciones
asociadas al tipo de datos. Estas operaciones constituyen el interface del tipo de datos y
los algoritmos que implementan esas operaciones son los únicos que tienen acceso
directo a la representación de los datos. Pero, restringiendo el acceso a los datos
exclusivamente al uso de esas operaciones, los procedimientos que usan ese interface
para tratar estos datos son independientes de la representación empleada (de ahí la idea
de abstracción). El propósito final es conseguir una implementación para siempre puesto
que tales procedimientos no tienen porqué reescribirse al cambiar la representación de
los datos. Por tanto, los programadores que implementan las estructuras de datos y las
operaciones asociadas pueden trabajar independientemente de los que diseñan
procedimientos basados en dichas operaciones, siempre que esté claramente establecido
el comportamiento esperado de las operaciones.
Informática II. 2005/2006 1
2. Estructuras Dinámicas de Datos. Listas Pilas y Colas Tema 2.
Los tipos de datos (TD) básicos comunes a la mayoría de los lenguajes son simples
o compuestos:
• Los tipos simples más comunes son el tipo Entero, el tipo Real, el tipo
Booleano, y el tipo Carácter,
• Los tipos compuestos más frecuentes son los vectores o Arreglos (array), los
Registros (record), y los Conjuntos (set).
Los correspondientes tipos abstractos de datos se establecen especificando las
operaciones a las que van asociados. Las operaciones más comunes son las siguientes.
• Operaciones aritméticas: +, −, *, /
• Operaciones lógicas: ∧ (AND), ∨ (OR), ¬ (NOT)
• Operaciones comparativas: <, >, =, ≤, ≥, ≠
Las correspondientes estructuras de datos en PASCAL tienen los identificadores
INTEGER, REAL, BOOLEAN, CHAR, SET, RECORD, ARRAY, ...
Ejemplo: Los conjuntos finitos de enteros se pueden representar a partir del tipo de datos
array o vector. Las operaciones a contemplar incluirían, al menos un constructor para
obtener un conjunto vacío o uno unitario, operaciones de manipulación como las
pertenencia de un elemento y la pregunta de si está vacío, y de modificación como la unión
o diferencia.
Una posible declaración de variables para esta estructura de datos es:
TYPE Conjunto = RECORD
Contenido: Array[1..100] of Elemento ;
Tamaño: Integer ;
END ;
Una posible implementación de estas operaciones es la siguiente.
a) Constructores:
PROCEDURE Construye_Vacio( A : Conjunto ) ;
BEGIN
A.Tamaño := 0 ;
END ;
PROCEDURE Construye_Unitario( A : Conjunto ;
e : Elemento ) ;
BEGIN
A.Tamaño := 1 ;
A.Contenido[1] := e ;
END ;
b) Manipuladores:
Function Pertenece( e : Elemento ;
A : Conjunto ) : Boolean ;
VAR i : Integer ;
BEGIN
Informática II. 2005/2006 2
3. Estructuras Dinámicas de Datos. Listas Pilas y Colas Tema 2.
Pertenece := False ;
FOR i := 1 TO A.Tamaño DO
IF A.Contenido[i] = e THEN
Pertenece := True ;
END ;
Function Es_Vacio( A : Conjunto ) : Boolean ;
BEGIN
Es_Vacio := A.Tamaño = 0 ;
END ;
c) Modificadores:
PROCEDURE Union ( A1,A2 : Conjunto ;
Unido : Conjunto ) ;
VAR i : Integer ;
BEGIN
Unido := A1 ;
FOR i := 1 TO A2.Talla DO
BEGIN
IF Pertenece(A1,A2.Contenido[i]) THEN
ELSE BEGIN
A1.Contenido[Talla] := A2.Contenido[i] ;
A1.Talla ;= A1.Talla + 1 ;
END ;
END ;
END ;
PROCEDURE Diferencia ( A1,A2 : Conjunto ;
Restado : Conjunto ) ;
VAR i,j,k : Integer ;
BEGIN
Restado := A1 ;
FOR i := 1 TO A2.Talla DO
BEGIN
IF Pertenece(A1,A2.Contenido[i]) THEN
ELSE BEGIN
FOR j := 1 TO A1.Tamaño DO
IF A1.Contenido[j] = A2.Contenido[i] THEN
k := j ;
A1.Contenido[k] := A1.Contenido[A1.Tamaño]
A1.Tamaño := A1.Tamaño – 1 ;
END ;
END ;
END ;
Una representación alternativa basada en vectores consiste en representar
directamente la función característica; es decir, la componente i-ésima del vector es 1 si el
número i está en el conjunto y 0 en otro caso. Para esta implementación, algunas
operaciones son más sencillas y otras más complicadas de implementar. Desde el punto de
vista de los usuarios, lo relevante es el consumo de espacio y tiempo al realizarlas. Otro
aspecto a tener en cuenta es el espacio necesario para representar los datos. Utilizando la
función característica, el tamaño de los vectores debe ser fijado de antemano
Informática II. 2005/2006 3
4. Estructuras Dinámicas de Datos. Listas Pilas y Colas Tema 2.
2. Estructuras Dinámicas de Datos.
Las Estructuras Dinámicas de Datos (EDD) son las que utilizan una cantidad de
memoria variable. Se construyen utilizando el tipo de datos puntero o apuntador: cuyos
valores corresponden a direcciones de memoria (entre las que se incluye una dirección
nula especial denominada NIL). Las operaciones usuales del correspondiente tipo
abstracto de datos son: NEW y DISPOSE.
El tipo de datos abstracto concreto que se implementa depende de la declaración.
Es necesario diferenciar claramente entre la variable apuntadora (declarada de la forma
^Tipo) y la variable apuntada (declarada a continuación, generalmente como un registro;
Tipo RECORD …).
La estructura dinámica de datos se puede representar de la forma:
p]-->(v q]-->(u
Un ejemplo de la posible declaración para un tipo de datos dinámico elemental es
la siguiente:
TYPE Tipo_P = ^Tipo_V ;
VAR p,q : Tipo_P
Las operaciones de asignación y comparación:
p := q ; p^ := q^ ;
p = q ; p^ = q^ ;
Otras tipos abstractos de datos basados en estructuras dinámicas de datos son las
Listas, las Colas, las Pilas, los Árboles, los Grafos, etc..
3. Representación y manipulación de Listas.
Una lista consiste en una cantidad arbitraria de elementos ordenados. Una Lista
es, a la vez, un TD (tipo de datos), un TAD (tipo abstracto de datos) o una ED (estructura
de datos). La especificación formal más simple del tipo lista son las Listas simplemente
enlazadas. Una lista simplemente enlazada está constituida por una cantidad arbitraria de
elementos del mismo tipo donde todo elemento lleva un enlace al siguiente elemento de la
lista. Además, el enlace del último elemento es un valor especial FIN DE LISTA (NIL) y
un enlace específico permite acceder al primer elemento de la lista.
Las listas simplemente enlazadas: constituyen un tipo de datos, un tipo abstracto
de datos y una estructura de datos.
El Tipo de Datos:
Existen diferentes formas sencillas de Representación de una lista simplemente
enlazada como son:
Lista] →{elem;p]→{elem;p] → .... →{elem;p]→{elem;p]→
Lista elem elem elem elem
Informática II. 2005/2006 4
5. Estructuras Dinámicas de Datos. Listas Pilas y Colas Tema 2.
El Tipo Abstracto de Datos:
Las operaciones más comunes con las listas son, en principio, la Inserción de un
nuevo elemento, la Eliminación de un elemento, Buscar un elemento, preguntar ¿es
vacía?, pero existen otras como la creación, eliminación de la lista, la concatenación, etc.
Pero además en cada uno de los casos hay diversas particularizaciones usuales. Por
ejemplo las Inserciones del nuevo elemento se pueden hacer: al principio de la lista, al final
de la misma, delante de un cierto elemento, o detrás, o en determinado orden, etc..
La Estructura de Datos:
Existen diferentes estructuras de datos correspondientes a los conceptos de tipos de
datos abstracto de tipo lista, pero en general, conviene usar memoria dinámica; es decir
emplear el tipo punteros lo que convierte a la estructura de datos en una estructura
dinámica de datos (EDD).
La declaración de tipo correspondiente puede ser la siguiente:
Type Tipo_Puntero = ^Tipo_Elemento
Tipo_Elemento = Record
Valor : Tipo_Valor ;
Siguiente : Tipo_Puntero ;
End ;
Tipo_Lista = Tipo_Puntero ;
Var Lista : Tipo_Lista ;
3.1. Operaciones.
Las operaciones a realizar con las listas pueden concretarse de distinta manera. Se
pueden considerar inserciones, al principio de la lista, al final, detrás de un elemento dado,
delante de dicho elemento, etc. Análogamente, las eliminaciones pueden afectar al primer
elemento, al último o a un elemento dado. En este caso, será necesario, en primer lugar,
buscar dicho elemento, por lo que en ocasiones conviene establecer previamente otras
operaciones. También es frecuente que sea necesario determinar alguna característica de
las circunstancias en la que se realizan las operaciones para tratar casos especiales. Esto
también puede llevar a la necesidad de considerar otras operaciones como ocurre con la
pregunta sobre la lista ¿es vacía?
Una propuesta de implementaciones para estas operaciones es la siguiente:
1. Inserciones:
1.a. Insertar al principio.
Procedure Insertar_Cabeza(
Var Lista : Tipo_Lista ;
Valor_Nuevo : Tipo_Valor );
Var Elemento_Nuevo : Tipo_Puntero ;
Begin
Informática II. 2005/2006 5
6. Estructuras Dinámicas de Datos. Listas Pilas y Colas Tema 2.
New(Elemento_Nuevo) ;
Elemento_Nuevo^.Valor := Valor_Nuevo ;
Elemento_Nuevo^.Siguiente := Lista ;
Lista := Elemento_Nuevo ;
End ;
1.b. Insertar al final.
Procedure Insertar_Cola(
Var Lista : Tipo_Lista ;
Valor_Nuevo : Tipo_Valor );
Var Elemento_Nuevo : Tipo_Puntero ;
Elemento_Auxiliar : Tipo_Puntero ;
Begin
If Lista = Nil
Then Begin
New(Elemento_Nuevo) ;
Elemento_Nuevo^.Valor := Valor_Nuevo ;
Elemento_Nuevo^.Siguiente := Nil ;
Lista := Elemento_Nuevo ;
End
Else Begin
Elemento_Auxiliar := Lista ;
While Elemento_Auxiliar^.Siguiente <> Nil
Do Elemento_Auxiliar :=
Elemento_Auxiliar^.Siguiente ;
New(Elemento_Nuevo) ;
Elemento_Nuevo^.Valor := Valor_Nuevo ;
Elemento_Nuevo^.Siguiente := Nil ;
Elemento_Auxiliar^.Siguiente :=
Elemento_Nuevo ;
End ;
End ;
1.c. Insertar detrás de un elemento.
El procedimiento es más sencillo que los anteriores; una vez encontrado el
elemento dado tras el cual realizar la inserción basta con las asignaciones de punteros:
Nuevo^.Siguiente := Dado^.Siguiente ;
Dado^.Siguiente := Nuevo ;
1.d. Insertar delante de un elemento:
En este caso se observa una mayor dificultad debido a que los enlaces no se pueden
invertir. Una posibilidad para solucionar este inconveniente es usar una lista doblemente
enlazada que se analizará más adelante donde existan enlaces al siguiente y al anterior
elemento de la lista.
Informática II. 2005/2006 6
7. Estructuras Dinámicas de Datos. Listas Pilas y Colas Tema 2.
2. Eliminaciones.
2.1. Eliminar el primero.
La parte fundamental es:
Aux := Lista ;
Lista := Lista^.Siguiente ;
Dispose(Aux) ;
2.2. Eliminar uno dado.
Para esta operación se hace necesaria previamente la operación Buscar.
3. Buscar
La operación buscar se puede implementar a través de una Function de la manera
siguiente:
FUNCTION BUSCAR ( x : T_Val ;
L : T_Lis ) : Boolean ;
VAR p : T_Lis ;
BEGIN
p := Nil
While (p <> Nil) and (p^.Val <> x )
Do p := p^.Sig ;
Buscar := p ;
END ;
4. ¿es vacía?
Finalmente, esta pregunta es una operación que se implementaría por:
Function Vacia( L : T_Lis ) : Boolean ;
Begin
Vacia := L = Nil ;
End ;
3.2. Tipos de Listas.
Dependiendo de las aplicaciones a considerar y de algunas otras cuestiones, puede
ser conveniente acudir a otro tipo de listas o de implementaciones que contemplen
aspectos especiales. Por ejemplo, es frecuente que las listas a tratar tengan que estar
ordenadas en algún sentido y que sea necesario o conveniente mantener dicho orden en las
inserciones, o aprovecharlo en la búsqueda. Esto lleva a reconsiderar aspectos de las
definiciones de las operaciones o de su implementación. Otro aspecto relevante en este
sentido es la existencia posible de elementos repetidos.
Informática II. 2005/2006 7
8. Estructuras Dinámicas de Datos. Listas Pilas y Colas Tema 2.
Otros tipos de listas, como las listas circulares o las listas doblemente enlazadas,
pueden requerir la reconsideración de algunas operaciones o pueden también venir
motivadas por características de estas operaciones. Las listas circulares se obtienen al
considerar el primer elemento como siguiente al último. Entonces no tiene sentido hablar
de primer ni último elemento y el puntero de acceso a la lista puede acceder a cualquiera de
sus elementos. En las listas doblemente enlazadas se puede acceder desde un elemento al
siguiente y al anterior. Puede ser conveniente, en tal caso disponer de punteros al principio
y final de la lista, de forma que se pueda recorrer desde ambos extremos.
4. Concepto e implementación de Pilas.
Las pilas y las colas constituyen los dos tipos de listas más importantes en las
aplicaciones informáticas. Las pilas son listas donde los elementos siempre entran o salen
por el principio mientras que las colas son listas donde los elementos siempre entran por el
principio y siempre salen por el final. Son usuales emplear los términos en inglés stack y
queue y se suele hacer referencia a ellas como listas tipo LIFO y FIFO respectivamente.
Estas siglas provienen de las expresiones en inglés: Last-In-First-Out y Fisrt-In-First-Out
que viene a decir que el último en entrar es el primero en salir (pila) y que el primero en
entrar es el primero en salir (cola).
La representación de una pila es la siguiente:
Pila] →{valor;p]→{valor;p]→{valor;p]→{valor;p]→
Las operaciones básicas, debido a las reglas concretas, necesitan menos
especificaciones. En lugar de insertar y eliminar se puede hablar de meter y sacar un
elemento. Las cinco operaciones básicas que son suficiente para casi todas las aplicaciones
son: averiguar si la pila está vacía, Meter un nuevo elemento en la pila, Sacar un elemento
de la pila, Crear una pila vacía, y Eliminar una pila (presumiblemente vacía). Es frecuente
utilizar los términos en inglés push y pop para las operaciones de meter y sacar un
elemento y denominar cabeza (head) o tope (top) al primer elemento.
Una propuesta de implementación es:
Procedure Push( Var P : Pila ; e : Elem ) ;
Begin
e^.Sig := P ;
P := e ;
End ;
Procedure Pop( Var P : Pila ) : Elem ;
Begin
Pop := P ;
P := P^.Sig ;
End ;
Informática II. 2005/2006 8
9. Estructuras Dinámicas de Datos. Listas Pilas y Colas Tema 2.
También es posible una representación mediante memoria estática (array) de las
pilas. En este caso, es necesario establecer un tamaño máximo de la pila y las operaciones
push y pop se describen en el ejemplo siguiente:
a) Operación Push:
Pila
cabeza
1 2 3 n−1 n n+1 max
23 5 34 77 34 ¿? ¿?
Push 25
cabeza
1 2 3 n−1 n n+1 max
23 5 34 77 34 25 ¿? ¿?
b) Operación Pop:
Pila
cabeza
1 2 3 n−1 n n+1 max
23 5 34 77 34 25 23
Pop 34
cabeza
1 2 3 n−1 n n+1 max
23 5 34 77 34 25 23
5. Concepto e implementación de Colas.
Las colas son en principio algo más complejas que las pilas porque hay que
gestionar los dos extremos de la lista, uno para meter elementos y el otro para sacar. Se
suelen denominar a los elementos extremos cabeza (head) y cola (tail) (Obsérvese que en
inglés hay dos términos distintos queue y tail para los dos conceptos para los que en
español utilizamos un solo término: cola).
La representación de una cola es la siguiente:
Cola] →{valor;p]→{valor;p]→{valor;p]→{valor;p]→
Para tratar más cómodamente la cabeza y la cola se emplea a veces una lista
doblemente enlazada y dos punteros, uno a cada uno de los extremos. Sin embrago, ello
implica un mayor número de instrucciones en las operaciones básicas.
Informática II. 2005/2006 9
10. Estructuras Dinámicas de Datos. Listas Pilas y Colas Tema 2.
Una propuesta de implementación de las operaciones estándares: push y pop para
una cola con doble enlace es la siguiente:
Procedure Push( Var C : Cola ; e : Elem ) ;
Begin
e^.Sig := Cola.head ;
Cola.head^.Ant := e ;
e^.Ant := Nil ;
Cola.head := e ;
End ;
Procedure Pop( Var C : Cola ) : Elem ;
Begin
Pop := Cola.Tail ;
Cola.Tail := Cola.Tail^.Ant ;
Cola.Tail^.Sig := Nil ;
End ;
También es posible la representación mediante memoria estática (array) de las
colas. En este caso, es necesario utilizar dos indicadores para el primer y último elemento
de la cola. Las operaciones push y pop se describen en el ejemplo siguiente:
a) Operación Push:
Cola
primero último
1 2 i i+1 j j+1 max
46 13 34 73 52 37 51
Push 63
primero último
1 2 i i+1 j j+1 max
46 13 34 73 52 63 51
b) Operación Pop:
Cola
primero último
1 2 i i+1 j j+1 max
46 13 34 73 52 63 51
Pop 34
primero último
1 2 i i+1 j j+1 max
46 13 34 73 52 63 51
Obsérvese que, de esta forma se agota el espacio sin necesidad si el tamaño de la
cola permanece estable y entran y salen muchos elementos. La solución está en usar una
lista circular
Informática II. 2005/2006 10