Documentos de Académico
Documentos de Profesional
Documentos de Cultura
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
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
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)
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.
Precondicin: Ninguna Postcondicin: Decide si la cola c tiene elementos o no. Por tanto, la cola c no se modifica.
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.
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.
Indice final
Indice principio
11
0
Array elementos
E0
...
E9
E10
E11
...
E max - 1
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
-1
-1
q->arrayelementos
Programacin II
Pgina 4/18
-1
q->arraylementos
E1
-1
q->arrayelementos
E1
E2
-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
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
E2
E3
q->principio
2
q->arrayelementos
E2
E3
E4
q->principio
4 E1 EliminarCola (&q)
q->final
2
q->arraylementos
E2
E3
E4
E5
q->principio
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
Programacin II
Pgina 7/18
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; } }
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; }
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
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.
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
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; }
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]; } }
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
4
q->arrayelementos
4
q->arrayelementos
E1
E2
Programacin II
Pgina 12/18
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
E2
E3
E4
E5
q->principio
2
q->arrayelementos
E2
E3
E4
E5
q->principio
2
q->arrayelementos
E6
E7
E3
E4
E5
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; }
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
Elemento de la cola
E1 dato
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 */
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
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; }
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; }
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
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