Sei sulla pagina 1di 14

Alg. y Estr. Datos-I / Fund. Progr.-II (R. Ferrs, J.

Albert)

COLAS
12

11.1 Fundamentos
Las colas son secuencias de elementos caracterizadas porque las operaciones de insercin y
borrado se realizan sobre extremos opuestos de la secuencia. La insercin 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 extrado 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 irn saliendo de la
cola en el orden en que entraron. Por esa razn, las colas tambin se conocen con el nombre
de listas FIFO (First In First Out, el primero que entra es el primero que sale).
Estructura Cola
A B C D E F ...

Borrado Insercin

Las colas, al igual que las pilas, resultan de aplicacin habitual en muchos problemas
informticos. Una aplicacin comn de las colas se da
es la organizacin de tareas de un ordenador. En general, un ordenador posee un nmero
reducido de unidades de proceso (1 o 2 CPUs) y, sin embargo, debe ejecutar muchos
programas simultneamente. Para poder hacer esto, los programas que se deben ejecutar en
el ordenador son almacenados en una cola, para ir procesando secuencialmente todos los
trabajos. 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 continuacin.
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.
Anlogamente a las pilas, es necesario definir el conjunto de operaciones bsicas para
especificar adecuadamente una estructura cola. Estas operaciones seran:
- Crear una cola vaca.
- Determinar si la cola est vaca, 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.

Pg. 1
Tema 12. Colas

Al igual que realizamos con las pilas, haremos una declaracin un poco ms 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
CrearCola ( ) Cola
Encolar ( Cola , Valor ) Cola
Desencolar ( Cola ) Cola
PrimeroCola ( Cola ) Valor
ColaVacia ( Cola ) Lgico

Axiomas
q Cola, x Valor se cumple que:
ColaVacia ( CrearCola ( ) ) cierto
ColaVacia ( Encolar ( q, x ) ) falso
Desencolar ( CrearCola ( ) ) error

Desencolar ( Encolar ( q, x ) )
{ ColaVacia si ColaVacia q = cierto
Encolar Desencolar q , x sino
PrimeroCola ( CrearCola ( ) ) error

PRIMERO_COLA ( Encolar ( q, x ) )
{x si ColaVacia q = cierto
PrimeroCola q sino
Estos axiomas vienen a decir bsicamente lo siguiente:
Cuando se crea una cola (CrearCola) est vaca, mientras que una cola en la que, al menos,
hemos puesto un elemento no lo est.
Tanto intentar eliminar un elemento, como consultar el primer elemento de una cola recin
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 vaca, o el primero de la cola si la cola ya contena otros
elementos.

12.2 Representacin de Colas en C++


Al igual que con las pilas, el primer paso de la implementacin ser decidir el prototipo de los
mtodos que vamos a utilizar.
La idea bsica ser seguir en la misma linea del tema anterior, buscando la mxima similitud
entre las operaciones de pilas y colas.
As las operaciones del interfaz que tendremos sern las siguientes, recordando que las
operaciones que puedan devolver errores, devolvern un valor lgico.

Pg. 2
Alg. y Estr. Datos-I / Fund. Progr.-II (R. Ferrs, J. Albert)

class Cola
{
public:
Cola ();
bool Encolar (Valor);
bool Desencolar ();
bool PrimeroCola (Valor &);
bool ColaVacia ();

private:
//Todava por definir
};

Para determinar concretamente cada una de estas operaciones y su implementacin, es


necesario especificar un tipo de representacin para las colas. Dependiendo de esta
representacin tendremos diferentes formas de construir el tipo.

12.2.1. Implementacin mediante estructuras estticas


La representacin de una cola finita en forma de vector es una tarea algo ms compleja que la
realizada para el caso de las pilas. Adems de un array unidimensional, son necesarias un par
de variables que indiquen dnde est el inicio de la cola y dnde el final.
Si son ini y fin las dos variables que hacen referencia a los extremos de la estructura.
En este caso, la definicin privada del tipo cola sera:
class Cola
{
public:
//...

private:
typedef Valor Vector[MAX];
Vector datos;
int ini, fin;
};

Sea una cola q cuyos elementos son (a, b, c, d, e), siendo a su primer elemento y e el ltimo.
La representacin grfica de la implementacin de q mediante un array, podra ser:

q = (a, b, c, d, e)

Pg. 3
Tema 12. Colas

0 1 2 3 4 MAX-1

a b c d e ...


inicio fin
Hay que tener en cuenta que los extremos de la secuencia se pueden ir desplazando a medida
que se realizan operaciones sobre la cola. As, por ejemplo, aadir (Encolar) el elemento f a
la cola q implicar desplazar el ndice fin a la siguiente posicin del array:

q.Encolar ('f')

0 1 2 3 4 5

a b c d e f ...


inicio fin

Igualmente, se eliminamos un elemento de la cola (Desencolar), el inicio de la cola se


desplazar al siguiente elemento, que pasa a ser el nuevo primer elemento de la cola:

q.Desencolar ()

0 1 2 3 4 5

a b c d e f ...


inicio fin
Las posiciones de inicio y fin siempre delimitan el conjunto de valores que forman parte
de la cola, con independencia de los datos contenidos en otras posiciones del array. As por
ejemplo, la figura anterior nos est diciendo que la cola q est formada por los elementos (b,
c, d, e, f).
Tambin se podra seguir el criterio de mantener siempre el inicio de la cola en la posicin 0
del array, pero eso implicara tener que desplazar todos los elementos de la cola una posicin
hacia la izquierda cada vez que se eliminase un elemento. Este proceso sera muy poco
eficiente, puesto que tendra un coste lineal con el nmero de elementos almacenados en la
cola. Por esa razn, no vamos a tratar esta posibilidad.
Un problema que tiene la representacin que estamos presentando es determinar la condicin
de cola llena Cmo determinar que no espacio para almacenar ms elementos? Un visin

Pg. 4
Alg. y Estr. Datos-I / Fund. Progr.-II (R. Ferrs, J. Albert)

simplista nos hara pensar que la cola est llena cuando el ndice fin apunta a la ltima
posicin del vector (fin == MAX-1). En realidad, esta condicin no indica necesariamente
que los elementos de la cola estn ocupando todas las posiciones del array, ya que es posible
que exista espacio libre, por haber ido borrando elementos, en las primeras posiciones del
array.
Un aprovechamiento ms eficiente del espacio reservado para los datos se obtiene
interpretando el array donde guardamos la informacin contenida en la cola como si fuese
circular. De esa manera, cuando se de el caso fin == MAX-1, ser posible insertar nuevos
elementos en la cola si los primeros elementos del array estn libres.
Para trabajar de forma sencilla con esta representacin ser conveniente definir una operacin
auxiliar que nos lleve de un ndice a su siguiente dentro de la nueva secuencia circular de
ndices. Esta operacin se limitar a incrementar el ndice si ste es menor que MAX-1 y a
volver a empezar en cero si se alcanza el valor MAX-1.
int Cola::Siguiente (int i)
{
return ( (i + 1) % MAX );
}

o lo que es lo mismo:
int Cola::Siguiente (int i)
{
if ( i == (MAX-1) )
return (0);
else
retrun ( i+1 );
}
Con esta interpretacin la condicin de cola llena se dar cuando inicio == Siguiente
(fin), es decir, el inicio de la cola est a continuacin del final. Por ejemplo:
q = (a, b, c, d, e, f, g)

0 1 2 3 4 5 6

f g a b c d e


fin inicio

Esta forma de representacin de una cola suele ser la ms habitual y recibe el nombre de cola
circular.

Pg. 5
Tema 12. Colas

Antes de proceder a la implementacin de las operaciones, es preciso comentar un ltimo


detalle: Cul es la condicin de cola vaca? Cmo es posible detectar que se han eliminado
todos los elementos de la cola?
Cada vez que se elimina un elemento se desplaza el ndice inicio, dejando fin fijo. La
situacin en que quede un nico elemento en la cola ser semejante a:
q = (g)

0 1 2 3 4 5 6

? g ? ? ? ? ?


inicio
fin

Si se elimina un elemento ms la cola estar vaca y la situacin ser:


q = ( )

0 1 2 3 4 5 6

? ? ? ? ? ? ?


fin inicio
Entonces, se cumple que inicio == Siguiente (fin) La misma condicin que se
cumple cuando la cola est llena!
Para evitar esta ambigedad y poder establecer condiciones diferentes para las situaciones de
cola llena y cola vaca, se establece que el ndice inicio se retrase una posicin respecto al
primer elemento de la cola. Siempre apunta a la posicin anterior al primer elemento y nunca
se utiliza la posicin de inicio para almacenar un elemento (se desaprovecha una posicin del
array). Esto hace que la situacin cuando la cola est llena sea:
q = (a, b, c, d, e, f)

0 1 2 3 4 5 6

e f a b c d


fin inicio

Pg. 6
Alg. y Estr. Datos-I / Fund. Progr.-II (R. Ferrs, J. Albert)

donde se cumple, al igual que antes, que inicio == Siguiente (fin).


Cuando la cola tenga un nico elemento la situacin ser:
q = (g)

0 1 2 3 4 5 6


inicio fin

Si se elimina un elemento ms la cola estar vaca y la situacin ser:


q = ( )

0 1 2 3 4 5 6


inicio
fin
Ahora, la condicin cambia. La cola est vaca cuando inicio == fin.
Como ya tenemos claro el esquema que se puede seguir, vamos a proceder a la
implementacin de las operaciones:
Operacin CrearCola
La creacin de la cola se realizar mediante el constructor por defecto. La tarea que deber
realizar ser establecer un estado inicial en el que no existen elementos en la cola. Es decir,
inicio y fin deben coincidir:
Cola::Cola ()
{
inicio = 0;
fin = 0;
}
Se podra haber fijado cualquier posicin, como el tratamiento del array va a ser circular no
importa en que posicin se empiece a introducir elementos.

Pg. 7
Tema 12. Colas

Operacin ColaVacia
Esta operacin permitir determinar si la estructura tiene o no elementos almacenados. Como
se ha dicho anteriormente, la cola estar vaca cuando inicio y fin coincidan:
bool Cola::ColaVacia ()
{
return (inicio == fin);
}

Operacin Encolar
La operacin, aplicada sobre un cola y un valor, almacena el valor al final de la cola. Esta
operacin est restringida por el tipo de representacin escogido. En este caso, la utilizacin
de un array implica que se tiene un nmero mximo de posibles elementos en la pila, por lo
tanto, es necesario comprobar, previamente a la insercin, que realmente hay espacio en la
estructura para almacenar un nuevo elemento. Con est consideracin, el algoritmo de
insercin sera:
bool Cola::Encolar (Valor x)
{
bool ok = true;

if ( inicio == Siguiente(fin) )
ok = false; //Cola llena
else
{
fin = Siguiente (fin);
datos[fin] = x;
}
return (ok);
}

Operacin Desencolar
La operacin de borrado elimina de la estructura el elemento situado en la primera posicin
(despus de inicio). Eliminar un elemento de la cola consiste fundamentalmente en
desplazar inicio a la siguiente posicin. Puesto que no es posible eliminar fsicamente los
elementos de un array, lo que se hace es dejar fuera del rango vlido de elementos al primero
de ellos.
bool Cola::Desencolar ()
{
bool ok = true;

if ( inicio == fin )
ok = false; //Cola vaca

Pg. 8
Alg. y Estr. Datos-I / Fund. Progr.-II (R. Ferrs, J. Albert)

else
inicio = Siguiente (inicio);
return (ok);
}

Operacin PrimeroCola
La operacin de consulta permite conocer el elemento almacenado en la cima de la pila,
teniendo en cuenta que si la pila est vaca no es posible conocer este valor.
bool Cola::PrimeroCola (Valor & x)
{
bool ok;

if (inicio == fin)
ok = false; //Cola vaca
else
{
x = datos[siguiente (inicio)];
ok = true;
}
return (ok);
}

12.2.2. Implementacin mediante estructuras dinmicas


Al igual que se hizo en el tema anterior, es posible representar el tipo Cola mediante un
esquema de reserva dinmica de memoria (punteros). En este caso, los elementos que
constituirn la cola no estarn almacenados de manera consecutiva en memoria, como en un
array, sino que se irn creando dinmicamente (durante la ejecucin del programa) y se irn
distribuyendo aleatoriamente en la memoria. Para que estos elementos dispersos puedan
formar una secuencia es preciso que estn relacionados o enlazados entre s. Lo que permite el
tipo puntero es establecer estos enlaces entre los elementos. De manera que un elemento (o
nodo) de la cola no estar formado exclusivamente por un elemento del tipo Valor, sino que
se tratar de un dato compuesto que incluir adicionalmente un puntero para enlazar con el
siguiente elemento de la secuencia. Grficamente, una cola q cuyos elementos son (a, b, c, d,
e), siendo a su primer elemento, se representara de manera enlazada de la siguiente forma:
q = (a, b, c, d, e)
inicio fin


a
d
c
d
e

Pg. 9
Tema 12. Colas

Con esta forma de implementacin, y siguiendo los mismos razonamientos realizados en el


tema anterior para el tipo Pila, el interfaz de la clase Cola quedara como sigue:
class Cola
{
public:
Cola ();
Cola (const Cola&);
~Cola ();
const Cola& operator= (const Cola&);
void Encolar (Valor);
bool Desencolar ();
bool PrimeroCola (Valor &);
bool ColaVacia ();
private:
struct Nodo;
typedef Nodo* Puntero;
struct Nodo
{
Valor info;
Puntero sig;
};
Puntero inicio, fin;
void Vaciar();
void Copiar (const Cola&);
};

Se puede observar como se incluye un constructor de copia, el operador asignacin y un


destructor para resolver los problemas de gestin de memoria (copia y eliminacin de objetos)
al manejar estructuras construidas mediante reserva dinmica de memoria.
Las operaciones Copiar y Vaciar aparecen de nuevo como operaciones auxiliares que
ayudan a construir otras operaciones.
Los nicos datos almacenados en los objetos de esta clase ser los punteros que indican la
posicin del primer y del ltimo elemento de la cola.
Ahora la implementacin de cada una de las operaciones queda como sigue:
Operacin CrearCola
Slo es preciso indicar que inicialmente los punteros inicio y fin no hacen referencia a
ningn nodo, puesto que la cola se crea vaca.
Cola::Cola ()
{
inicio = NULL;
fin = NULL;

Pg. 10
Alg. y Estr. Datos-I / Fund. Progr.-II (R. Ferrs, J. Albert)

Operacin ColaVacia
Necesita verificar si el puntero a inicio ( o fin) referencia algn nodo.
bool Cola::ColaVacia ()
{
return (inicio == NULL);
}

Operacin Encolar
Es preciso reservar memoria para cada nuevo elemento que se desee aadir a la cola, puesto
que no hay espacio reservado para l a priori. Adems de sto, es preciso que el nuevo
elemento se enlace adecuadamente con el resto de elementos de la cola. El nuevo nodo
siempre ser el ltimo de la cola y se aadir detrs de fin. Adems, hay que tener en cuenta
que este elemento tambin ser el primero en el caso en que la cola estuviese vaca.
void Cola::Encolar (Valor x)
{
Puntero p_aux;

p_aux = new Nodo;


p_aux->info = x;
p_aux->sig = NULL;
if (inicio == NULL)
inicio = p_aux;
else
fin->sig = p_aux;
fin = p_aux;
ok = true;
}
}

Operacin Desencolar
En una estructura dinmica es posible liberar la memoria reservada previamente si ya nos es
necesaria. En este caso, cuando se desapila un elemento, es posible liberar la memoria
asociado al nodo que ocupa en la pila. Luego, adems de avanzar la cima para que el elemento
quede fuera de la pila se debe liberar la memoria que ocupaba. La funcin sera la siguiente:
bool Cola::Desencolar ()
{
bool ok;
Puntero p_aux;

if (inicio == NULL)

Pg. 11
Tema 12. Colas

ok = false;
else
{
p_aux = inicio;
inicio = inicio->sig;
if (inicio == NULL)
fin = NULL;
delete p_aux;
ok = true;
}
return (ok);
}

Operacin PrimeroCola
Esta operacin debe devolver el valor almacenado la primera posicin de la cola. En este caso,
la informacin almacenada en el campo info del nodo.
bool Cola::PrimeroCola (Valor & x)
{
bool ok;

if (inicio == NULL)
ok = false;
else
{
x = inicio->info;
ok = true;
}
return (ok);
}

Constructor de copia para la clase Cola


El constructor de copia tiene como finalidad permitir que se creen nuevos objetos de la clase
como como copias de otros ya existentes (paso de argumentos por valor, creacin de objetos
temporales, etc). De manera anlogo a la implementacin de pilas, tenemos una operacin
privada Copiar() que realiza la copia de una cola en otra y el constructor de copia se limita a
utilizarla:
Cola::Cola (const Cola& c)
{
Copiar(c)
}

Pg. 12
Alg. y Estr. Datos-I / Fund. Progr.-II (R. Ferrs, J. Albert)

La funcin Copiar ser prcticamente idntica a la construidas para pilas, puesto que el
proceso a realizar el mismo:
void Cola::Copiar (const Cola& c)
{
Puntero p_aux, dup;

Vaciar();

p_aux = c.inicio;
while ( (p_aux != NULL) && ok )
{
dup = new Nodo;
dup->info = p_aux->info;
dup->sig = NULL;
if (inicio == NULL)
inicio = dup;
else
fin->sig = dup;
fin = dup;
p_aux = p_aux->sig;
}
}

void Cola::Vaciar()
{
while (Desencolar());
}

Operador asignacin
El operador asignacin tiene el mismo problema que la copia de objetos cuando se manejan
punteros. Se trata tambin de copiar un objeto en otro. Para que se pueda utilizar de manera
correcta el operador asignacin sobre elementos de la clase pila implementada con punteros es
preciso realizar lo que se llama una sobrecarga del operador asignacin (=). Esto significa
especificar cmo se debe realizar la asignacin de objetos de esta clase. La implementacin de
la sobrecarga del operador = (operator=) sera idntica a la del operador de copia (de ah la
conveniencia de haber definido la funcin Copiar).
const Cola& Cola::operator= (const Cola& c)
{
Copiar(c)
return (*this);
}

Pg. 13
Tema 12. Colas

Destructor
El destructor de una clase es nico, a diferencia del constructor, y no tiene argumentos. Su
nombre es el mismo de la clase, pero precedido del smbolo ~. Suponiendo que existe la
funcin auxiliar Vaciar que se ha utilizado ya en la funcin Copiar, el destructor de la clase
Cola tendra la siguiente forma:
Cola::~Cola ()
{
Vaciar();
}

Pg. 14

Potrebbero piacerti anche