Está en la página 1de 18

TEMA 3: TAD COLA

ndice 1. Introduccin 2. Especificacin Formal 3. Realizaciones de la estructura Cola 3.1. Realizacin mediante memoria esttica con pseudocdigo 3.2. Realizacin mediante memoria dinmica con pseudocdigo

Introduccin
Al igual que nos ocurre con la estructura Pila, la estructura que estudiaremos a continuacin tambin la podemos encontrar en la vida real en mltiples ejemplos: cuando esperamos en la caja de un supermercado para pagar nuestra compra; cuando vamos a cualquier espectculo, cine, teatro, circo, etc., y nos colocamos ante la taquilla para adquirir la entrada; o cualquier otra situacin parecida, lo normal es hacerlo formando una cola o fila donde el primero que llega es el primero en obtener el servicio y sale de la misma. Esta poltica de funcionamiento se denomina FIFO (First In First Out), es decir, el primer elemento en entrar a la estructura es el primer elemento en salir de ella. Dentro de la informtica las colas se utilizan en mltiples reas, as por ejemplo, los Sistemas Operativos la utilizan en la gestin de recursos que pueden ser compartidos por varios procesos (gestin de memoria, tiempo de procesador, etc) . Para la estructura Pila, donde slo exista un extremo para acceder a los elementos y no era vlido intentar obtener un elemento de otra forma, decamos que si no actuamos correctamente, en la vida real corremos el riesgo de que la estructura se desmorone y en el aspecto que a nosotros nos concierne, la estructura deja de ser una Pila. En el caso que estamos estudiando, estructura Cola, tambin podra ocurrir que en los ejemplos expuestos alguien intentase colarse o saltarse el turno establecido, o incluso desistiese y abandonase la cola antes de que le tocase su turno. Consideraremos que el incumplimiento de la poltica de funcionamiento expuesto para la estructura Cola har que sta deje de serlo. Definicin:

Una cola es un conjunto ordenado de elementos homogneos, en el cual los elementos se eliminan por uno de sus extremos, denominado PRINCIPIO o CABEZA, y se aaden por el otro extremo, denominado FINAL. Su funcionamiento sigue una poltica FIFO, es decir, el primer elemento en entrar a la estructura es el primer elemento en salir de ella.

Cuando decimos que se trata de un conjunto ordenado, al igual que ocurre con las pilas, hablamos del orden que se establece entre los elementos al incorporarse a la estructura, nunca a un orden en relacin con el valor de los datos. Esto quiere decir que los elementos, excepto el primero y el ltimo, tiene un anterior y un siguiente. Adems, cuando decimos que los elementos de la cola son homogneos, significa que todos son de igual tipo de datos.

Programacin II

Pgina 1/18 28/01/2013

Segn todo esto, para poder trabajar sobre un elemento de la cola es necesario que dicho elemento est ocupando la posicin de principio de la Cola, ser el primero. La forma grfica de representar una Cola es: FINAL PRINCIPIO

E3

E2

E1

Las operaciones normales para gestionar la estructura son aadir y quitar elementos, luego grficamente sobre la Cola anteriormente representada vemos su evolucin tras sucesivas operaciones, dndonos cuenta que se trata se una estructura dinmica: Aadir: FINAL E4 E3 E2 E1 PRINCIPIO

Aadir:

FINAL

E5

E4

E3

E2

E1

PRINCIPIO

Eliminar:

FINAL

E5

E4

E3

E2

PRINCIPIO

Eliminar:

FINAL

E5

E4

E3

PRINCIPIO

Aadir:

FINAL

E6

E5

E4

E3

PRINCIPIO

Especificacin Formal
Las operaciones que permitirn manejar la estructura Cola, entre otras, son las siguientes: ColaVacia: Crea una cola vaca, sin elementos. AadirCola: Inserta un elemento por el final de la cola y devuelve la cola resultante. PrimeroCola: Devuelve el elemento que ocupa la posicin del principio de la cola. EliminarCola: Elimina el elemento de que ocupa la posicin de principio de la cola y devuelve la cola resultante. EsColaVacia: Determina si una cola tiene elementos o no. Donde las operaciones constructoras de la estructura son precisamente ColaVacia y Aadir, que con sucesivas aplicaciones permiten conseguir cualquier cola. AadirCola (AadirCola (AadirCola (ColaVacia, e1), e2), e3)

La especificacin formal para el TAD Cola es la siguiente: TAD TCOLA Valores: Coleccin de elementos homogneos y que opera segn un modelo FIFO.

Programacin II

Pgina 2/18

Sintaxis: * ColaVacia * AadirCola (TCOLA, TELEMENTO) PrimeroCola (TCOLA) EliminarCola (TCOLA) EsColaVacia (TCOLA) Semntica: c TCOLA, e TELEMENTO

TCOLA TCOLA TELEMENTO TCOLA BOOLEAN

EsColaVacia (ColaVacia) EsColaVacia (AadirCola (c, e)) PrimeroCola (ColaVacia) PrimeroCola (AadirCola (c, e)

TRUE FALSE ERROR si EsColaVacia (c) entonces e si no PrimeroCola (c) ERROR si EsColaVacia (c) entonces ColaVacia si no AadirCola ((EliminarCola (c), e)

EliminarCola (ColaVacia) EliminarCola (AadirCola (c, e))

Realizaciones de la estructura COLA


Vamos a definir con ms detalle las operaciones de manejo de la estructura Cola definida conceptualmente, indicando los requisitos que deben de cumplir para realizarlas y si los parmetros son de entrada, de salida o ambas cosas, etc. ColaVacia ( /* E/S */ TCOLA c) Precondicin: Ninguna Postcondicin: Obtiene la cola c sin elementos. Por tanto, la cola c se modifica.

AadirCola ( /* E/S */ TCOLA c; /* E */ TELEMENTO e )

Precondicin: Ninguna Postcondicin: Almacena por el final de la cola c el elemento e y devuelve la cola resultante. Por tanto, la cola c se modifica.

EsColaVacia ( /* E */ TCOLA c; /* S */ BOOLEAN respuesta)

Precondicin: Ninguna Postcondicin: Decide si la cola c tiene elementos o no. Por tanto, la cola c no se modifica.

PrimeroCola ( /* E */ TCOLA c; /* S */ TELEMENTO e)

Precondicin: La cola c no puede estar vaca. Postcondicin: Obtiene el elemento que ocupa la posicin del principio de la cola c. Por tanto, la cola c no se modifica.

EliminarCola ( /* E/S */ TCOLA c)

Precondicin: La cola c no puede estar vaca

Programacin II

Pgina 3/18

Postcondicin: Elimina de la cola c el elemento que ocupa la posicin del principio de la cola y devuelve la cola resultante. Por tanto, la cola c se modifica.

Realizacin mediante memoria esttica en C


Basndonos en la realizacin hecha para el tipo Pila, representaremos la estructura de datos a travs del tipo estructura o registro con los siguientes campos: un array donde se almacenen los elementos de la cola y adems dos ndices que indiquen en cada momento qu elemento acta como principio de la cola y qu elemento acta de final de la cola. Como ocurri en el caso de estructura Pila, nuevamente nos encontramos que el uso de un array implica un tamao mximo que se debe fijar a priori y que por tanto, limita la capacidad de elementos sobre la estructura que estamos definiendo, perdiendo una de sus caractersticas importantes, ser una estructura con tamao dinmico. Grficamente sera:

Indice final

Indice principio

11

0
Array elementos

E0

...

E9

E10

E11

...

E max - 1

Estructura TCola Implementacin mediante array

Las declaraciones para poder hacer esta implementacin son: #define MAX ... typedef .... TELEMENTO ; typedef struct { TELEMENTO arrayelementos[MAX]; int principio, final; } STCOLA; typedef STCOLA * TCOLA; Variables TCOLA q; Vamos a ver con un ejemplo el funcionamiento de la estructura y cmo se va comportando la misma despus de aplicar sucesivas operaciones. Inicialmente supondremos una Cola vaca, luego la operacin ser ColaVaca que tendr como resultado una cola sin elementos y por tanto el ndice de final y principio ser 1. ColaVacia (&q)
q->final q->principio

/* nmero mximo de elementos que podr almacenar la cola */

-1

-1
q->arrayelementos

Programacin II

Pgina 4/18

AadirCola (&q, E1)


q->final q->principio

-1
q->arraylementos

E1

AadirCola (&q, E2)


q->final q->principio

-1
q->arrayelementos

E1

E2

AadirCola (&q, E3)


q->final q->principio

-1
q->arrayelementos

E1

E2

E3

PrimeroCola (q): esta operacin debe devolver el elemento ms antiguo en la cola, es decir, el que ocupa la posicin 0 del vector. Por tanto, el resultado de esta operacin es E1 que vendr dado por: q->arrayelementos [q->principio + 1] EliminarCola (&q)
q->final q->principio

0
q->arrayelementos

E1

E2

E3

PrimeroCola (q): el resultado de esta operacin es E2

Programacin II

Pgina 5/18

EliminarCola (&q)
q->final q->principio

1
q->arrayelementos

E1 EliminarCola (&q)
q->final

E2

E3

q->principio

2
q->arrayelementos

E1 AadirCola (&q, E4)


q->final

E2

E3

q->principio

3 E1 AadirCola (&q, E5)


q->final

2
q->arrayelementos

E2

E3

E4

q->principio

4 E1 EliminarCola (&q)
q->final

2
q->arraylementos

E2

E3

E4

E5

q->principio

4 E1 AadirCola (&q, E6)


q->final

3
q->arrayelementos

E2

E3

E4

E5

q->principio

5 E1 E2 E3

3
q->arrayelementos

E4

E5

E6

Programacin II

Pgina 6/18

PrimeroCola (q): el resultado de esta operacin es E5 AadirCola (&q, E7): con esta operacin se han completado las posiciones del vector.
q->final q->principio

6 E1 EliminarCola (&q)
q->final

3
q->arrayelementos

E2

E3

E4

E5

E6

E7

q->principio

6 E1 E2 E3

4
q->arrayelementos

E4

E5

E6

E7

PrimeroCola (q): el resultado de esta operacin es E6

Segn lo expuesto en el ejemplo se puede concretar que:

principio: contiene el ndice de una posicin anterior a la correspondiente al elemento ms antiguo


de la cola. final: contiene el ndice de la posicin correspondiente al elemento aadido ms recientemente. La condicin de cola vaca es: principio = final Ahora, segn la definicin del tipo Cola anteriormente indicado, vamos a implementar las operaciones propias del TAD Cola: ColaVacia ( /* E/S */ TCOLA q) Precondicin: Ninguna Postcondicin: Obtiene la cola q sin elementos. Por tanto, la cola q se modifica. void ColaVacia (TCOLA *q) { *q = (TCOLA) malloc (sizeof(STCOLA)) (*q)->final = -1; (*q)->principio = -1; }

Programacin II

Pgina 7/18

AadirCola ( /* E/S */ TCOLA q; /* E */ ELEMENTO e )

Precondicin: La cola no debe estar llena. Postcondicin: Almacena por el final de la cola q el elemento e y devuelve la cola resultante. Por tanto, la cola q se modifica. void AnadirCola (TCOLA *q, TELEMENTO e) { int respuesta; respuesta = EsColaLlena (*q); if (respuesta == 1) printf("ERROR, la cola esta llena"); else { (*q)->final++ ; (*q)->arrayelementos [(*q)->final] = e; } }

EsColaVacia ( /* E */ TCOLA q; /* S */ BOOLEAN respuesta)

Precondicin: Ninguna Postcondicin: Decide si la cola q tiene elementos o no. Por tanto, la cola q no se modifica. int EsColaVacia (TCOLA q) { int respuesta = (q->final == q->principio); return respuesta; }

PrimeroCola ( /* E */ TCOLA q; /* S */ ELEMENTO e)

Precondicin: La cola q no puede estar vaca. Postcondicin: Obtiene el elemento que ocupa la posicin de principio de la cola q. Por tanto, la cola q no se modifica. void PrimeroCola (TCOLA q , TELEMENTO *e) { int respuesta; respuesta = EsColaVacia(q); if (respuesta == 1) printf("ERROR, la cola no tiene elementos"); else *e = q->arrayelementos [q->principio + 1]; }

Programacin II

Pgina 8/18

EliminarCola ( /* E/S */ TCOLA q)

Precondicin: La cola q no puede estar vaca Postcondicin: Elimina de la cola q el elemento que ocupa la posicin del principio de la cola y devuelve la cola resultante. Por tanto, la cola q se modifica. void EliminarCola (TCOLA *q) { int respuesta; respuesta = EsColaVacia(*q); if (respuesta == 1) printf("ERROR, la cola no tiene elementos"); else (*q)->principio++; }

La operacin AadirCola implementada con vectores, tiene como precondicin comprobar si hay sitio en el vector para insertar el nuevo elemento, una forma de comprobar esto sera simplemente ver si el valor de q.final coincide con el ndice de la ltima posicin del vector, es decir, Max 1. Su implementacin sera:

Precondicin: Ninguna Postcondicin: Decide si la cola q no tiene capacidad para nuevos elementos. Por tanto, la cola q no se modifica. int EsColaLlena (TCOLA q) { if (q->final == MAX-1) return 1; else return 0; } Considerando que esto es as, hemos alcanzado el final del array, y podemos asumir que no hay posibilidad de aadir nuevos elementos a la estructura. Pero eso no es del todo cierto, ya que como se puede observar en el ejemplo anterior, existen huecos libres al principio del array, dejados por los elementos eliminados. Por tanto, con esta implementacin no estamos optimizando el uso del array. Una forma de solucionar este problema sera que cada vez que se elimina un elemento de la cola se desplacen todos los elementos de la cola hacia esa posicin liberada, dejando siempre vacantes las posiciones del final para admitir nuevos elementos. As, se mantiene fija en la primera posicin del array el principio de la cola y la condicin de cola llena seguira siendo la implementada. Sin embargo, esta solucin no es la ms eficiente, ya que el nmero de movimientos con los elementos del array es excesivo.

EsColaLlena ( /* E */ TCOLA q; /* S */ BOOLEAN respuesta)

Programacin II

Pgina 9/18

Otra forma ms eficiente y adecuada de solucionar el problema es suponer el array como una estructura circular, es decir, reutilizar las posiciones correspondientes a elementos anteriormente eliminados de la cola. Para conseguirlo se considerar que la posicin siguiente a la ltima del array ser precisamente la primera posicin de vector. Grficamente sera: [0] [1] [2] [3] [4] [5]

La implementacin de la estructura de datos va a ser igual que antes, una estructura que tendr tres campos. La capacidad de la estructura seguir siendo limitada y depender de la dimensin del array donde se almacenan los elementos de la cola, por tanto, llegar un momento en el que no se puedan insertar ms elementos, la cola estar llena. Ahora vamos a analizar el uso que le daremos a los campos que antes nos indicaban la posicin del principio y del final de la cola. En primer lugar hay que ver que al tratarse de un array circular, la posicin siguiente a una dada, i, no siempre ser la posicin i+1, por lo que definiremos una operacin Siguiente que nos permita obtener la posicin correcta segn el caso: int Siguiente ( int pos ) { if (pos < MAX - 1) return (pos+1); else return 0; } Vamos a implementar nuevamente las operaciones del TAD Cola utilizando un array circular. ColaVacia ( /* E/S */ TCOLA q) Precondicin: Ninguna Postcondicin: Obtiene la cola q sin elementos. Por tanto, la cola q se modifica. void ColaVacia (TCOLA * q) { *q = (TCOLA) malloc (sizeof (STCOLA) ); (*q)->final = MAX - 1; (*q)->principio = MAX - 1; }

Programacin II

Pgina 10/18

EsColaVacia ( /* E */ TCOLA q; /* S */ BOOLEAN respuesta)

Precondicin: Ninguna Postcondicin: Decide si la cola q tiene elementos o no. Por tanto, la cola q no se modifica. int EsColaVacia ( TCOLA q ) { if (q->final == q->principio) return 1; else return 0; }

PrimeroCola ( /* E */ TCOLA q; /* S */ ELEMENTO e)

Precondicin: La cola q no puede estar vaca. Postcondicin: Obtiene el elemento que ocupa la posicin del principio de la cola q. Por tanto, la cola q no se modifica. void PrimeroCola (TCOLA q , TELEMENTO *e) { int respuesta, sig; respuesta = EsColaVacia(q); if (respuesta == 1) printf("ERROR, la cola no tiene elementos"); else { sig = Siguiente (q->principio); *e = q->arrayelementos [sig]; } }

EliminarCola ( /* E/S */ TCOLA q)

Precondicin: La cola q no puede estar vaca Postcondicin: Elimina de la cola q el elemento que ocupa la posicin del principio de la cola y devuelve la cola resultante. Por tanto, la cola q se modifica.

void EliminarCola (TCOLA * q) { int respuesta, sig; respuesta = EsColaVacia(*q); if ( respuesta == 1) printf("ERROR, ...."); else { sig = Siguiente ((*q)->principio); (*q)->principio = sig; } }

Programacin II

Pgina 11/18

Recordemos que la operacin AadirCola implementada con arrays exige como precondicin comprobar si hay sitio en el arrays para insertar el nuevo elemento. Dado que ahora consideramos el array circular, analicemos con un ejemplo esta nueva situacin para obtener conclusiones antes de pasar a la implementacin de ambas operaciones: EsColaLlena y AadirCola. ColaVacia (&q)
q->final q->principio

4
q->arraylementos

AadirCola (&q, E1)


q->final q->principio

4
q->arrayelementos

E1 AadirCola (&q, E2)


q->final q->principio

4
q->arrayelementos

E1

E2

Programacin II

Pgina 12/18

AadirCola (&q, E3)


q->final q->principio

4
q->arrayelementos

E1

E2

E3

PrimeroCola (q): Ser el elemento que ocupa la posicin Siguiente(q->principio), es decir: E1 AadirCola (&q, E4)
q->final q->principio

4
q->arrayelementos

E1

E2

E3

E4

EliminarCola (&q)
q->final q->principio

0
q->arraylementos

E1 EliminarCola (&q)
q->final

E2

E3

E4

q->principio

1
q->arrayelementos

E1

E2

E3

E4

PrimeroCola (q): Ser el elemento que ocupa la posicin Siguiente(q->principio), es decir: E3 AadirCola (&q, E5)
q->final q->principio

1
q->arrayelementos

E1

E2

E3

E4

E5

Programacin II

Pgina 13/18

EliminarCola (&q)
q->final q->principio

2
q->arrayelementos

E1 AadirCola (&q, E6)


q->final

E2

E3

E4

E5

q->principio

2
q->arrayelementos

E6 AadirCola (&q, E7)


q->final

E2

E3

E4

E5

q->principio

2
q->arrayelementos

E6

E7

E3

E4

E5

AadirCola (&q, E8)


q->final q->principio

2
q->arrayelementos

E6

E7

E8

E4

E5

Segn este ejemplo, sabemos que la cola est llena, dado que tenemos ocupadas todas las posiciones del array. Sin embargo, dado que se cumple precisamente la condicin de cola vaca, es decir, el principio es igual al final, la cola estara vaca. Por tanto, para evitar esta situacin de ambigedad, debemos pensar en algo que nos permita diferenciar ambas situaciones. Una primera solucin sera aadir un nuevo campo numrico a la estructura del TAD Cola, que indique el nmero de elementos que contiene la cola. Por tanto, cuando la cola est vaca este campo valdr 0 y cuando est llena su valor ser MAX (dimensin del vector). El adoptar esta solucin implica tener que modificar la declaracin del TAD, as como sus operaciones. Otra solucin ms aceptada y menos costosa consiste en dejar siempre una posicin libre en la Cola. La posicin que se deja libre es justamente la posicin del array direccionada a travs de campo principio, y que es la anterior en el vector circular a la ocupada por el elemento ms antiguo de la cola. Pues bien, con esta implementacin, esta posicin nunca podr estar ocupada.

Programacin II

Pgina 14/18

Por tanto, la condicin de cola llena ser cuando el final de la cola se encuentre justo antes de esta posicin (q->principio), es decir, cuando el siguiente elemento al ltimo coincida con la posicin que debe quedarse vaca.

Precondicin: Ninguna Postcondicin: Decide si la cola q no tiene capacidad para nuevos elementos. Por tanto, la cola q no se modificar. int EsColaLlena ( TCOLA q ) { int pos_sig = Siguiente(q->final) ; if (pos_sig == q->principio) return 1 ; else return 0; }

EsColaLlena ( /* E */ TCOLA q; /* S */ BOOLEAN respuesta)

AadirCola ( /* E/S */ TCOLA q; /* E */ ELEMENTO e )

Precondicin: La cola no debe estar llena. Postcondicin: Almacena por el final de la cola q el elemento e y devuelve la cola resultante. Por tanto, la cola q se modifica. void AnadirCola ( TCOLA * q , TELEMENTO e) { int resp, pos_sig ; resp = EsColaLlena (*q) ; if (resp == 1) printf("ERROR, la cola esta llena"); else { pos_sig = Siguiente ((*q)->final); (*q)->final = pos_sig; (*q)->arrayelementos [(*q)->final] = e; } }

Lo mismo que ocurra con la pila, el uso de una estructura esttica, el array, para manejar una estructura dinmica, la cola, siempre tiene el mismo problema, la capacidad de almacenamiento es limitada y no se contempla en la definicin o especificacin del TAD.

Programacin II

Pgina 15/18

Realizacin mediante memoria dinmica en C


Igual que en el caso del TAD Pila, ahora utilizaremos los punteros para implementar el TAD Cola a travs de memoria dinmica. Grficamente cada nodo de la Cola ser:

Elemento de la cola

Puntero al siguiente nodo

As, la estructura Cola sera como:


*q Principio final

E1 dato

Implementacin mediante variables dinmicas

E2 dato

. . .

E8 dato

Las declaraciones para poder hacer esta implementacin son: Tipos typedef ... TELEMENTO; typedef struct nodo /* tipo de datos correspondiente a los elementos de la cola */

{ TELEMENTO dato; struct nodo * sig; } TNodo;

typedef struct {TNodo * principio, * final; } STCOLA; typedef STCOLA * TCOLA; Variables TCOLA q;

Segn esta definicin del tipo Pila, las operaciones se podrn implementar como sigue: ColaVacia ( /* E/S */ TCOLA q) Precondicin: Ninguna Postcondicin: Obtiene la cola q sin elementos. Por tanto, la cola q se modifica. void ColaVacia ( TCOLA * q ) { *q = (TCOLA) malloc (sizeof (STCOLA) ) ; (*q)->final = NULL; (*q)->principio = NULL; }

Programacin II

Pgina 16/18

EsColaVacia ( /* E */ TCOLA q; /* S */ BOOLEAN respuesta)

Precondicin: Ninguna Postcondicin: Decide si la cola q tiene elementos o no. Por tanto, la cola q no se modifica. int EsColaVacia ( TCOLA q ) { if ( (q->final == NULL) && (q->principio == NULL) ) return 1; else return 0; }

PrimeroCola ( /* E */ TCOLA q; /* S */ ELEMENTO e)

Precondicin: La cola q no puede estar vaca. Postcondicin: Obtiene el elemento que ocupa la posicin del principio de la cola q. Por tanto, la cola q no se modifica. void PrimeroCola ( TCOLA q, TELEMENTO * e) { int respuesta; respuesta = EsColaVacia(q); if ( respuesta == 1) printf("ERROR, la cola no tiene elementos"); else *e = (q->principio)->dato; }

EliminarCola ( /* E/S */ TCOLA q)

Precondicin: La cola q no puede estar vaca Postcondicin: Elimina de la cola q el elemento que ocupa la posicin del principio de la cola y devuelve la cola resultante. Por tanto, la cola q se modifica.

void EliminarCola (TCOLA * q) { int respuesta; TNodo * aux; respuesta = EsColaVacia(*q); if ( respuesta == 1 ) printf("ERROR, "); else { aux = (*q)->principio; (*q)->principio = aux->sig; if ((*q)->principio == NULL) (*q)->final = NULL; free (aux); } }

Programacin II

Pgina 17/18

AadirCola ( /* E/S */ TCOLA q; /* E */ ELEMENTO e )

Precondicin: Ninguna. Postcondicin: Almacena por el final de la cola q el elemento e y devuelve la cola resultante. Por tanto, la cola q se modifica. void AnadirCola (TCOLA * q , TELEMENTO e) { int respuesta; TNodo * aux; aux = (TNodo *) malloc (sizeof (TNodo) ); aux->dato = e; aux->sig = NULL; respuesta = EsColaVacia (*q); if (respuesta == 1) (*q)->principio = aux; else (*q)->final->sig = aux; (*q)->final = aux; }

Programacin II

Pgina 18/18