Colas - WikiPNFI

Anuncio
Ricardo Ferrís Castell
Algoritmos y Estructuras de Datos I
12. COLAS
12.0 INTRODUCCIÓN .....................................................................................................................................................41
12.1 FUNDAMENTOS .....................................................................................................................................................41
12.2. REPRESENTACIÓN DE LAS COLAS EN C++............................................................................................................42
Implementación mediante estructuras estáticas: Colas lineales .............................................................................45
Implementación mediante estructuras estáticas: Colas circulares .........................................................................49
Implementación mediante estructuras dinámicas: Colas enlazadas .......................................................................51
12.0 Introducción
En este tema veremos las estructuras de datos lineales colas, su significado y las operaciones más
habituales sobre ellas, así como algunas posibles implementaciones con estructuras estáticas y
dinámicas en C++.
12.1 Fundamentos
Las colas son secuencias de elementos caracterizadas porque las operaciones de inserción y borrado
se realizan sobre extremos opuestos de la secuencia. La inserción se produce en el "final" de la
secuencia, mientras que el borrado se realiza en el otro extremo, el "inicio" de la secuencia.
Las restricciones definidas para una cola hacen que el primer elemento que se inserta en ella sea,
igualmente, el primero en ser extraido de la estructura. Si una serie de elementos A, B, C, D, E se
insertan en una cola en ese mismo orden, entonces los elementos irán saliendo de la cola en el
ordenen que entraron. Por esa razón, en ocasiones, las colas se conocen con el nombre de listas o
secuencias FIFO (First In First Out, el primero que entra es el primero que sale).
Estructura Cola
A
→
Borrado
B
C
D
E
F
...
→
Inserción
Las colas, al igual que las pilas, resultan de aplicación habitual en muchos problemas informáticos.
Quizás la aplicación más común de las colas es la organización de tareas de un ordenador. En
general, los trabajos enviados a un ordenador son "encolados" por éste, para ir procesando
secuencialmente todos los trabajos en el mismo orden en que se reciben. Cuando el ordenador
recibe el encargo de realizar una tarea, ésta es almacenada al final de la cola de trabajos. En el
momento que la tarea que estaba realizando el procesador acaba, éste selecciona la tarea situada al
principio de la cola para ser ejecutada a continuación. Todo esto suponiendo la ausencia de
prioridades en los trabajos. En caso contrario, existirá una cola para cada prioridad. Del mismo
modo, es necesaria una cola, por ejemplo, a la hora de gestionar eficientemente los trabajos que
deben ser enviados a una impresora (o a casi cualquier dispositvo conectado a un ordenador). De
esta manera, el ordenador controla el envio de trabajos al dispositivo, no enviando un trabajo hasta
que la impresora no termine con el anterior.
Análogamente a las pilas, es necesario definir el conjunto de operaciones básicas para especificar
adecuadamente una estructura cola. Estas operaciones serían:
Tema 12. Colas
41
Algoritmos y Estructuras de Datos I
Ricardo Ferrís Castell
- Crear una cola vacía.
- Determinar si la cola está vacía, en cuyo caso no es posible eliminar elementos.
- Acceder al elemento inicial de la cola.
- Insertar elementos al final de la cola.
- Eliminar elementos del inicio de la cola.
Al igual que realizamos con las pilas, haremos una declaración un poco más formal de estas
operaciones y los axiomas que las caracterizan:
Estructura
Cola ( Valor )
{* Valor será el tipo de datos que podremos guardar en la cola *}
Operaciones
CREAR_COLA ( ) → Cola
ENCOLAR ( Cola , Valor ) → Cola
DESENCOLAR ( Cola ) → Cola
PRIMERO_COLA ( Cola ) → Valor
COLA_VACIA ( Cola ) → Lógico
Axiomas
∀ queue ∈ Cola, x ∈ Valor se cumple que:
COLA_VACIA ( CREAR_COLA ( ) ) → cierto
COLA_VACIA ( ENCOLAR ( queue, x ) ) → falso
DESENCOLAR ( CREAR_COLA ( ) ) → error
PRIMERO_COLA ( CREAR_COLA ( ) ) → error
x si COLA_VACIA(queue) = true
PRIMERO_COLA ( ENCOLAR ( queue, x ) ) → 
PRIMERO_COLA ( queue ) sino
Estos axiomas vienen a decir básicamente lo siguiente:
Una cola recien creada (CREAR_COLA) está vacía, mientras que una cola en la que, al menos,
hemos puesto un elemento no está vacía.
Tanto intentar eliminar un elemento, como consultar el primer elemento de una cola recien creada,
produce un error.
Y finalmente la consulta de una cola en la que hemos insertado un nuevo elemento ‘x’, devolverá
‘x’ si la cola estaba vacia, o el primero de la cola si la cola ya contenia otros elementos.
12.2. Representación de las Colas en C++
Al igual que con las pilas, el primer paso de la implementación será decidir el prototipo de los
métodos que vamos a utilizar.
La idea básica será seguir en la misma linea del tema anterior, buscando la máxima similitud entre
las operaciones de pilas y colas.
Así las operaciones del interfaz que tendremos serán las siguientes, recordando que las operaciones
que puedan devolver errores, devolverán un boolean.
42
Tema 12. Colas
Ricardo Ferrís Castell
class Cola
{
public:
Cola
bool
bool
bool
bool
};
Algoritmos y Estructuras de Datos I
(void);
Encolar (Valor);
Desencolar (void);
PrimeroCola (Valor &);
ColaVacia (void);
private:
.??.
Para determinar concretamente cada una de estas operaciones y su implementación, es necesario
especificar un tipo de representación para las colas. Dependiendo de esta representación tendremos
diferentes implementaciones.
Ejemplo de utilización de colas
Con la interfaz propuesta ya somos capaces de utilizar la clase cola, y podemos realiza un ejemplo.
Realizar una función en C++ que nos diga el número de elementos que contiene una cola
pasada como parámetro.
Para saber el número de elementos tendremos que ir desencolandolos de la cola y
contando los elementos hasta que la cola se quede vacía. Para asegurarnos que la cola no
queda modificada podemos pasarla por valor, o pasarla por referencia y si en algún
momento la modificamos, devolverla antes de terminar la función a su valor original.
El algoritmo en este segundo caso sería:
Algoritmo ContarElementos
Entradas: Cola que;
Salidas: Cola que;
Entero num_ele;
Variables Cola q_aux;
Entero x;
Inicio
q_aux = CrearCola ()
num_ele = 0
Mientras (No ColaVacia(que) ) Hacer
x = Desencolar (que)
Encolar (q_aux, x)
num_ele = num_ele + 1
Fin_mientras
Mientras (No ColaVacia (q_aux) ) Hacer
Encolar (que, Desencolar (q_aux) )
Fin_mientras
Devolver (num_ele)
Fin
Tema 12. Colas
43
Algoritmos y Estructuras de Datos I
Ricardo Ferrís Castell
El organigrama correspondiente a este algoritmo sería el siguiente:
Si aplicamos la interfaz que hemos definido para la clase cola en C++, podemos realizar
la función en C++:
int ContarElementos (Cola & que)
{
int num_ele;
Cola q_aux;
Valor x;
num_ele = 0;
while (!que.ColaVacia () )
{
b_aux = que.Desencolar (x);
b_aux = q_aux.Encolar (x);
num_ele++;
}
while (!q_aux.ColaVacia () )
{
b_aux = q_aux.Desencolar (x);
b_aux = que.Encolar (x);
}
}
return num_ele;
No tenemos en cuenta el posible error del método Desencolar, porque para llegar a esa
llamada hemos tenido en cuenta que la cola no esté vacía. El error de Encolar tampoco
lo hemos tenido en cuenta porque si los elementos cabían en la cola original, también van
a caber en la cola auxiliar.
Aunque podríamos controlar la cola vacía a través del error que devuelve la función
desencolar:
int ContarElementos (Cola & que)
{
int num_ele;
Cola q_aux;
Valor x;
num_ele = 0;
while (!que.Desencolar (x) )
44
Tema 12. Colas
Ricardo Ferrís Castell
{
}
Algoritmos y Estructuras de Datos I
b_aux = q_aux.Encolar (x);
num_ele++;
while (!q_aux.Desencolar (x) )
b_aux = que.Encolar (x);
}
return num_ele;
Implementación mediante estructuras estáticas: Colas lineales
La representación de una cola finita en forma de vector es una tarea algo más compleja que la
realizada para el caso de las pilas. Además de un array unidimensional, son necesarias un par de
variables que indiquen dónde está el inicio de la cola y dónde el final.
Si son ini y fin las dos variables que apuntan a los extremos de la estrutura, normalmente se
adopta el convenio de que la variable ini sea siempre la posición real del primer elemento y que la
variable fin siempre apunte a la siguiente posicion de la cola donde podemos insertar nueva
información. De esta manera, se cumplirá que ini=fin si y sólo si la cola está vacía, y la condición
inicial para indicar que se ha creado una cola vacía será ini=fin=0.
Tal como hicimos con la definición del tipo pila, la definición ‘compacta’ del tipo cola sería:
class Cola
{
public:
.??.
};
private:
Vector info;
int ini, fin;
Con este esquema de representación, se puede pasar a especificar el conjunto de operaciones
necesarias para definir una cola:
Operación CREAR_COLA
Esta operación consistirá en definir la variable del tipo nuevo declarado, Cola (array que permitirá
almacenar la información y las varibles que apuntarán a los extremos de la estructura) e iniciar los
valores de manera que se indique explícitamente que la cola, trás la creación, está vacía.
(1) Variables
queue: Pila;
(2) Asignación de pila vacía
queue.ini ← 0
queue.fin ← 0
Esta operación, en C++, se convierte en el constructor por defecto:
K
Cola::Cola (void)
{
ini = 0;
fin = 0;
}
K
Tema 12. Colas
45
Algoritmos y Estructuras de Datos I
Ricardo Ferrís Castell
Operación COLA_VACIA
Con las condiciones establecidas, basta comprobar si los valores del inicio y el final de la cola son
iguales:
Algoritmo Cola_Vacia
Entrada
queue: Cola
Salida
(CIERTO, FALSO)
Inicio
Si ( queue.ini = queue.fin ) entonces
Devolver ( CIERTO )
Sino
Devolver ( FALSO )
Fin_si
Fin
K
bool Cola::ColaVacia (void)
{
bool b_aux;
if (ini == fin)
b_aux = true;
else
b_aux = false;
}
return b_aux;
K
O lo que sería lo mismo, devolver directamente la comparación ini == fin.
K
bool Cola::ColaVacia (void)
{
return ini == fin;
}
K
Operación de inserción de información (ENCOLAR)
Al igual que en las pilas, la inserción de elementos está condicionada por la representación que se
hace de la estructura. Al representar la cola con un array (tamaño finito), es preciso comprobar
previamente si existe espacio disponible en la cola para almacenar más información. En el caso en
que se pueda insertar la nueva información, la colocaremos en el lugar correspondiente dentro del
vector y actualizaremos las marcas de inicio y final de la cola.
Algoritmo Encolar
Entradas
x: Valor
queue: Cola de Valor
Salidas
queue
Inicio
46
{* elemento que desea insertar *}
Tema 12. Colas
Ricardo Ferrís Castell
Algoritmos y Estructuras de Datos I
{* comprobar si en la cola se pueden insertar más elementos
{* esto es necesario por el tipo de representación de la estructura
*}
*}
Si ( queue.fin = MAX ) entonces
Error "cola llena"
Sino
queue.info [queue.fin] ← x
queue.fin ← queue.fin + 1
Fin_sino
Fin
K
bool Cola::Encolar (Valor x)
{
bool error;
if (fin == MAX)
error = true;
else
{
error = false;
info [fin] = x
fin++;
}
}
return error;
K
Operación de consulta de información (PRIMERO_COLA)
La consulta se hace a través de la posición que indica el campo Ini, y sólo si la cola no está vacía.
Algoritmo Primero_Cola
Entradas
queue: Cola de Valor
Salidas
Valor
Inicio
{* comprobar si existe información en la cola
{* esta operación no depende de la representación, siempre es necesaria
*}
*}
Si ( Cola_Vacia ( queue ) ) entonces
Error “cola vacia”
sino
Devolver ( queue.info [queue.ini] )
Fin_si
Fin
Tema 12. Colas
47
Algoritmos y Estructuras de Datos I
Ricardo Ferrís Castell
K
bool Cola::PrimeroCola (Valor & x)
{
bool error;
}
if (ColaVacia () )
error = true;
else
{
error = false;
x = info[ini];
}
return error;
K
Operación de eliminación de información (DESENCOLAR)
Para eliminar elementos de la estructura, es preciso determinar si realmente hay información que
extraer, sino el algoritmo debe detectar el error, independientemente de la representación concreta
de la cola.
Algoritmo Desencolar
Entradas
queue: Cola de Valor
Salidas
queue: Cola, x: Valor
Inicio
{* comprobar si se pueden eliminar elementos de la cola
{* esta operación no depende de la representación, siempre es necesaria
*}
*}
Si ( Cola_Vacia (queue) ) entonces
Error “cola vacia”
sino
{* Esta operación no sería realmente necesaria *}
queue.ini ← queue.ini + 1
Fin_si
Fin
K
bool Cola::Desencolar (void)
{
bool error;
}
if (ColaVacia () )
error = true;
else
{
error = false;
ini++;
}
return error;
K
48
Tema 12. Colas
Ricardo Ferrís Castell
Algoritmos y Estructuras de Datos I
Implementación mediante estructuras estáticas: Colas circulares
Hay que tener en cuenta que, de hecho, la condición de cola llena (queue.fin = MAX), considerada
en la operación de inserción, no indica necesariamente que existan n elementos en la cola, ya que es
posible que exista espacio libre, por haber ido borrando elementos en las primeras posiciones del
array.
Una solución obvia a este problema podría ser desplazar todos los elementos hacia la izquierda,
cada vez que se produce una operación de borrado, hasta alcanzar el principio del array. Sin
embargo, ésto no resulta demasiado eficiente, sobre todo cuando existen muchos elementos en la
cola y la operaciones de borrado e inserción son muy frecuentes.
Por lo tanto, la representación de una cola especificada por las anteriores operaciones, puede dar
lugar, en general, a una utilización ineficiente del espacio reservado para la estructura.
Una representación más eficiente se obtiene viendo el array donde guardamos la información
contenida en la cola como si fuese circular. De esa manera, cuando se de el caso queue.Fin=MAX,
será posible insertar nuevos elementos en la cola si los primeros elementos del array están libres.
Para trabajar de forma sencilla con esta representación será conveniente definir una operación
auxiliar que nos lleve de un indice a su siguiente dentro de la nueva secuencia circular de índices.
Esta operación se limitará a incrementar el índice si éste es menor que MAX y a volver a empezar
en cero si se alcanza el valor de MAX.
Algoritmo Siguiente
Entradas
ind: 0..MAX - 1
Salidas
0..MAX - 1
Inicio
{* La operación mod devuelve el valor del resto de la division entera entre ind y MAX *}
Devolver ( (ind + 1) mod MAX)
Fin
El método siguiente quedará, en la declaración del interfaz de la clase, como un método privado,
y su codificación en C++ será como sigue:
K
int Cola::Siguiente (int ind)
{
return (ind + 1) % MAX;
}
K
Con esta nueva representación, la comprobación de si una cola está o no vacía se mantiene
(queue.ini = queue.fin). Sin embargo, el resto de operaciones cambia ligeramente, ya que los
elementos ya no se insertarán o consultarán en la posición incrementada del índice, sino en la
posición “siguiente” siguiendo el patrón circular.
En primer lugar la iniciación de la estrucutra puede seguir haciéndose asignando los índices de
inicio y fin de cola a cero.
Apoyándonos en la función auxiliar siguiente, los algoritmo de inserción, consulta y borrado
quedarían de la siguiente forma:
Tema 12. Colas
49
Algoritmos y Estructuras de Datos I
Algoritmo Encolar
Entradas
x: Valor
queue: Cola de Valor
Salidas
queue
Inicio
Ricardo Ferrís Castell
{* elemento que se desea insertar *}
{* comprobar si en la cola se pueden insertar más elementos
{* esto es necesario por el tipo de representación de la estructura
*}
*}
Si ( Siguiente ( queue.fin ) = queue.ini ) entonces
Error "cola llena"
Sino
queue.info [queue.fin] ← x
queue.fin ← Siguiente (queue.fin)
Fin_sino
Fin
Destacar en este algoritmo la siguiente consideración: Si consideraramos la posibilidad de insertar
elementos en el vector hasta ocupar todos los elementos posibles del array tendríamos que la
condición de cola llena y cola vacia sería la misma (queue.ini = queue.fin). Por ello,
habitualmente se mantiene un elemento vacío entre la última posición ocupada y la última, de
manera que la consición de cola vacía se mantiene, mientras que la de cola llena se transforma en:
Siguiente (queue.fin) = queue.ini.
Si deseasemos utilizar ese hueco, de manera que la condición de cola llena y cola vacía no pudiese
distinguirse, sería necesario añadir una variable lógica que nos indicase el estado real de la cola (si
vacia o llena), sabiendo que sólo podemos llenar una cola tras hacer inserciones o sólo podemos
dejarla vacía tras eliminar elementos.
El algoritmo propuesto traducido a C++ quedará:
K
bool Cola::Encolar (Valor x)
{
bool error;
if (Siguiente (fin) == ini)
error = true;
else
{
error = false;
info[fin] = x;
fin = Siguiente (fin);
}
}
return error;
K
El método PrimeroCola no cambia de ninguna manera, y el método Desencolar sólo cambia en
el avance del índice ‘ini’
50
Tema 12. Colas
Ricardo Ferrís Castell
Algoritmos y Estructuras de Datos I
Algoritmo Desencolar
Entradas
queue: Cola de Valor
Salidas
queue
Inicio
{* comprobar si se pueden eliminar elementos de la cola
{* esta operación no depende de la representación, siempre es necesaria
*}
*}
Si ( Cola_Vacia (queue) ) entonces
Error “cola vacia”
sino
{* Esta operación no sería realmente necesaria *}
queue.Ini ← Siguiente (queue.Ini)
Fin_si
Fin
K
bool Cola::Desencolar (void)
{
bool error;
}
if (ColaVacia () )
error = true;
else
{
error = false;
ini = Siguiente (ini);
}
return error;
K
Implementación mediante estructuras dinámicas: Colas enlazadas
Creación de una cola: Constructor por defecto
Al igual que en el caso de pilas, desarrollaremos tres pasos para la creación de la cola dinámica:
(1) Definición de los tipos necesarios:
Tipo
Nodo_cola = Registro
Info: Valor
Sig : Puntero_a_Nodo_cola
Fin_reg
Tipo
Cola = Registro
Ini, Fin: Puntero_a_Nodo_cola
Fin_reg
Tema 12. Colas
51
Algoritmos y Estructuras de Datos I
Ricardo Ferrís Castell
(2) Declaración de una variable de este nuevo tipo (cola):
Var
queue: Cola
(3) Iniciación de la estructura como vacía:
Algoritmo Iniciar_Cola
Entradas
queue: Cola de Valor
Salidas
queue
Inicio
queu.ini ← NULO
queu.fin ← NULO
Fin
En C++, estos pasos se resumirían en la declaración de la variable:
K
Cola que;
K
La declaración de los tipos necesarios:
K
struct nodo
{
Valor info;
Puntero sig;
};
typedef nodo * Puntero;
K
La inclusión de la información necesaria en la parte privada de la clase:
K
class Cola
{
public:
.??.
};
private:
Puntero ini, fin;
K
Y la implementación del método constructor por defecto de la clase:
K
Cola::Cola (void)
{
ini = NULL;
fin = NULL;
}
K
52
Tema 12. Colas
Ricardo Ferrís Castell
Algoritmos y Estructuras de Datos I
Creación de una cola: Constructor de copia
Ya comentamos en Pilas la necesidad, en el caso de representación de información con estructuras
dinámicas, del constructor de copia.
Cuando se pasa un parámetro por valor, se realiza una copia de la información contenida en la
variable que se pasa por valor, pero solo de la información contenida en él.
Así, si la variable contiene punteros a diferentes espacios de memoria, el paso por valor, en
principio realizará una copia de estos valores sin más, de manera que la memoria referenciada
seguirá siendo la misma, y no tendremos una copia real de la información guardada.
Si queremos tener una copia de toda la información, deberemos incluir entre los métodos de la
clase, el constructor de copia.
El contructor de copia es un método que es llamado automáticamente cada vez que se realiza un
paso de parámetros por valor del objeto en concreto. Si existe el constructor de copia, éste es
llamado, sino se realiza sólo la copia de la información contenida en el objeto.
El prototipo del constructor de copia es:
Nombre_de_la_clase (const Nombre_de_la_clase &)
Al igual que el constructor por defecto, no devuelve ningún valor, ni siquiera void. Tiene como
nombre, el nombre de la clase, y como único parámetro un objeto por referencia constante, que será
el objeto del que queremos realizar una copia.
En el caso que tenemos, colas, el constructor de copia podría ser:
K
Cola::Cola (const Cola & que)
{
Puntero p_aux, q_aux;
ini = NULL;
p_aux = que.ini;
while (p_aux != NULL)
{
q_aux = new Nodo;
q_aux->info = p_aux->info;
if (ini == NULL)
ini = q_aux;
else
fin->sig = q_aux;
fin = q_aux;
}
}
p_aux = p_aux->sig;
K
Comprobación de cola vacía
De nuevo, la estructura estará vacía si y sólo si inicio no apunta a ningún nodo de la cola (es decir,
apunta a NULO.)
Tema 12. Colas
53
Algoritmos y Estructuras de Datos I
Ricardo Ferrís Castell
Algoritmo Cola_Vacia
Entrada
queue: Cola
Salida
(CIERTO, FALSO)
Inicio
Si (queue.ini = NULO) entonces
Devolver (CIERTO)
Sino
Devolver (FALSO)
Fin_si
Fin
K
bool Cola::ColaVacia (void)
{
return ini == NULL;
}
K
Acceso al primer elemento de la cola
Se puede acceder a este elemento de la cola mediante el puntero inicio que lo referencia.
Algoritmo Primero_Cola
Entradas
queue: Cola de Valor
Salidas
Valor
Inicio
{* comprobar si existe información en la cola
{* esta operación no depende de la representación, siempre es necesaria
*}
*}
Si ( Cola_Vacia ( queue ) ) entonces
Error “cola vacia”
sino
Devolver ( queue.info [queue.ini] )
Fin_si
Fin
K
bool Cola::PrimeroCola (Valor & x)
{
bool error;
}
if (ColaVacia () )
error = true;
else
{
error = false;
x = ini->info;
}
return error;
K
54
Tema 12. Colas
Ricardo Ferrís Castell
Algoritmos y Estructuras de Datos I
Operación de inserción
Al igual que en cualquier otra estructura dinámica, la inserción consta básicamente de tres pasos: El
primero de reserva del espacio necesario para el nuevo elemento; el segundo de asignación del valor
a insertar; y finalmente, el tercero de enlace del nuevo elemento en la estructura dinámica.
Algoritmo Encolar
Entrada
queue: Cola de Valor
x: Valor
Salida
queue
Variable
p_aux: puntero a Nodo_cola
Inicio
p_aux ← Crear_Espacio
p_aux^.Info ← x
p_aux^.Sig ← NULO
Si ( Cola_Vacia ( queue ) entonces
queue.Ini ← p_aux
Sino
queue.Fin^.Sig ← p_aux
Fin_si
queue.Fin ← p_aux
fin
La traducción a C++ es inmediata:
K
bool Cola::Encolar (Valor x)
{
bool error;
Puntero p_aux;
error = false;
p_aux = new Nodo;
p_aux->info = x;
p_aux->sig = NULL;
if (ColaVacia () )
ini = p_aux;
else
fin->sig = p_aux;
fin = p_aux;
}
return error;
K
Operación de eliminación de un elemento
Como en cualquier estructura dinámica, la eleiminación de información se realiza básicamente en
tres pasos: (1) Obtener la información del elemento a borrar; (2) desenlazar el elemento de la
Tema 12. Colas
55
Algoritmos y Estructuras de Datos I
Ricardo Ferrís Castell
estructura; y (3) finalmente liberar el espacio ocupado por el elemento para dejarlo accesible para
futuras llamadas.
Algoritmo Desencolar
Entrada
queue: Cola de Valor
Salida
queue
x: Valor
Variable
p_aux: puntero a Nodo_Cola
Inicio
Si(1) ( Cola_Vacia (queue ) entonces
Error “cola_vacia"
Sino(1)
{* 1 *}
x ← queue.Ini^.Info
{* 2 *}
p_aux ← queue.Ini
queue.Ini ← p_aux^.Sig
{* si tras borrar se vacia la cola, hay poner Fin a nulo *}
Si(2) ( Cola_Vacia ( queue ) entonces
queue.Fin ← NULO
Fin_si(2)
{* 3 *}
Fin
Liberar_Espacio ( p-aux )
Fin_si(1)
K
bool Cola::Desencolar (void)
{
bool error;
Puntero p_aux;
if (ColaVacia () )
error = true;
else
{
error = false;
p_aux = ini;
ini = ini->sig;
}
dispose p_aux;
}
return error;
K
56
Tema 12. Colas
Ricardo Ferrís Castell
Algoritmos y Estructuras de Datos I
Operación de borrado de la estructura: Destructor de la clase
Una variable, cuando acaba el bloque donde está declarada, termina su existencia y es liberado el
espacio que ocupa en memoria. Es decir, el sistema marca como libre ese espacio y lo deja
disponible para su reutilización.
En el caso de los objetos ocurre exactamente lo mismo, el espacio de datos que ocupa el objeto es
liberado por el sistema.
En el caso en que toda la información guardada por el objeto este declarada dentro del objeto
(estructuras estáticas) no existe ningún porblema: La memoria ocupada es liberada.
Las cosas son ligeramente diferentes en el caso en que parte de la información guardada por el
objeto no esté totalmente en el interior del objeto, sino que el objeto contenga enlaces a la memoria
ocupada por la información (caso dinámico). En este caso, la memoria que se libera cuando acaba el
bloque donde está declarado el objeto tan solo es la contenida en el objeto, es decir, solo los enlaces
que enlazan con la memoria donde está la información. Con esto, la memoria ocupada por la
información queda ‘ocupada’, mientras que las referencias de acceso para acceder a ella
desaparecen.
Esto es una cosa que debemos evitar, liberando antes de que desaparezca el ámbito de la variable, la
memoria ocupada por la información.
Un algoritmo que libera toda la memoria ocupada por una cola dinámica podría ser:
Algoritmo LiberarCola
Entrada
queue: Cola de Valor
Salida
queue
Variable
p_aux: puntero a Nodo_cola
Inicio
Mientras (No Cola_Vacia (queue) hacer
p_aux ← que.ini
que.ini ← que.ini^.sig
Liberar (p_aux)
fin_mientras
fin
En C++, para facilitar este proceso existe el método ‘destructor’ de la clase.
Al igual que los constructores, que son llamadso automáticamente cada vez que es necesario, el
destructor de la clase es llamado siempre que vaya a desaparecer el objeto. Si existe lo ejecuta y
libera elespacio ocupado por el objeto, y si no existe se limita a liberar el espacio ocupado por el
objeto.
Asi como puede haber varios constructores, sólo puede haber un destructor y su prototipo es:
~Nombre_De_La_Clase (void)
No devuleve ningún tipo, ni siquiera void, igual que el constructor por defecto. Tiene como nombre
el símbolo ‘~’ seguido del nombre de la clase. Y como parámetros sólo puede tener void.
Tema 12. Colas
57
Algoritmos y Estructuras de Datos I
Ricardo Ferrís Castell
K
Cola::~Cola (void)
{
Puntero p_aux;
}
while (!ColaVacia() )
{
p_aux = ini;
ini = ini->sig;
dispose (p_aux);
}
K
58
Tema 12. Colas
Descargar