Ampliación de informática TDA Cola Rocío Altelarrea Molinero Marta Andrés Andrés María Pérez Carbonero 1 Ampliación de informática TDA Cola 2 Ampliación de informática TDA Cola ÍNDICE 1. Descripción del TDA Cola _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 5-8 1.1. Definición y características . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 1.2. Diferentes implementaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-7 A) TDA Cola implementado con arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5-6 B) TDA Cola implementado con arrays circulares . . . . . . . . . . . . . . . . . . . . . . . 6 C) TDA Cola implementado con listas enlazadas . . . . . . . . . . . . . . . . . . . . . . 6-7 D) TDA Cola implementado con listas circulares . . . . . . . . . . . . . . . . . . . . . . . . 7 1.3. Bicolas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7-8 2. Utilidades del TDA Cola _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 10-14 2.1. Simulación . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11-14 2.2. Colas de prioridades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.3. Montículos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 3. Implementación en C mediante listas enlazadas _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 14-22 4. Bibliografía _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 23 3 Ampliación de informática TDA Cola 4 Ampliación de informática TDA Cola 1. DESCRIPCIÓN DEL TDA COLA 1.1. DEFINICIÓN Y CARACTERÍSTICAS Una cola es un tipo de dato abstracto cuyos elementos mantienen un cierto orden, sólo se pueden añadir elementos por un extremo, llamado final, y eliminar por el otro extremo, llamado frente. Son conocidas también como estructuras FIFO (First In First Out), el primero en entrar es el primero en salir. El símil cotidiano es una cola para comprar, por ejemplo, las entradas del cine. Los nuevos compradores sólo pueden colocarse al final de la cola, y sólo el primero de la cola puede comprar la entrada. Las características de las colas son: - Tipo de dato: dato que se almacena en la cola. - Operaciones: Crear cola: inicializa la cola como vacía. Es la primera operación a realizar en una cola. Borrar cola: elimina todos los elementos de la cola. Insertar (queue): añade un elemento por el final de la cola. Eliminar (dequeue): extrae el elemento frente de la cola. Cola vacía: comprueba si la cola no tiene elementos, devolviendo verdadero si no los tiene. Cola llena: comprueba si la cola está llena de elementos, devolviendo verdadero si lo está. Tamaño de la cola: devuelve el número máximo de elementos que puede contener la cola. 1.2. DIFERENTES IMPLEMENTACIONES El TDA Cola se puede implementar con arrays y con listas enlazadas. La utilización de arrays tiene el problema de que la cola no puede crecer indefinidamente, está limitada por el tamaño del array; sin embargo, el acceso a los extremos es muy eficiente. La utilización de listas enlazadas permite que el tamaño de la estructura se ajuste al de elementos de la cola; pero cada nodo necesita memoria extra para el enlace y además hay que tener en cuenta el límite de memoria de la pila del ordenador. A) TDA COLA IMPLEMENTADO CON ARRAYS La definición de una cola ha de contener un array para almacenar los elementos de la cola, y dos marcadores para mantener las posiciones frente y final de la cola; es decir, un marcador apuntando a la posición de cabeza de la cola y otro al primer espacio vacío 5 Ampliación de informática TDA Cola que sigue al final de la cola. Cuando un elemento se añade a la cola, se comprueba si el marcador final apunta a una posición válida, y si es así, se añade el elemento a la cola y se incrementa el marcador final en 1. Cuando un elemento se elimina de la cola, se prueba si la cola está vacía, y si no es así, se elimina el primer elemento de la cola y se incrementa el marcador frente en 1. El avance lineal de frente y final tiene un grave problema, deja huecos por la izquierda del array. Puede ocurrir que final alcance el índice más alto del array, no pudiéndose insertar nuevos elementos existiendo posiciones libres a la izquierda de frente. Una alternativa a esta situación es mantener fijo el frente de la cola al comienzo del array, lo que supone mover todos los elementos de la cola una posición hacia la izquierda cada vez que se elimine un elemento. Estos problemas quedan resueltos considerando el array como circular. B) TDA COLA IMPLEMENTADO CON ARRAYS CIRCULARES Un array circular une el extremo final de la cola con su extremo frente. Es el medio más eficiente para almacenar una cola en un array. Permite que el array completo se utilice para almacenar elementos de la cola sin dejar posiciones libres a las que no se puede acceder. El array se almacena de modo natural en la memoria tal como un bloque lineal de N elementos. Se necesitan dos marcadores para indicar la posición frente y final de la cola. La variable frente es siempre la posición del primer elemento de la cola y se avanza en el sentido de las agujas del reloj. La variable final es la posición de la última inserción en la cola; una nueva inserción supone mover final circularmente a la derecha y asignar el nuevo elemento. La simulación del movimiento circular de los índices se realiza utilizando la teoría de los restos, de tal forma que se generan índices de 0 a tamaño_maximo-1: Mover final adelante = (final + 1) % tamaño_maximo Mover frente adelante = (frente + 1) % tamaño_maximo C) TDA COLA IMPLEMENTADO CON LISTAS ENLAZADAS La realización de una cola con arrays exige reservar memoria contigua para el máximo de elementos previstos. Esto puede producir un desaprovechamiento de la memoria, también puede ocurrir que se llene la cola y no se pueda seguir con la ejecución del programa. Una alternativa es emplear memoria dinámica mediante una 6 Ampliación de informática TDA Cola lista enlazada, aún a pesar de tener el inconveniente de la memoria extra utilizada para realizar los encadenamientos entre nodos. Esta implementación utiliza dos punteros para acceder a la lista, frente y final. La variable puntero frente referida al primer elemento de la cola. La variable puntero final referida al último elemento en ser añadido a la cola. Al ser una estructura dinámica puede crecer y decrecer según las necesidades, el límite está en la memoria libre del ordenador. D) TDA COLA IMPLEMENTADO CON LISTAS CIRCULARES Es una variante de la implementación con listas enlazadas. Mediante una lista circular, por conveniencia, se establece que el puntero de acceso a la lista es el que hace referencia al último elemento insertado, y que el nodo siguiente es considerado el primero. Así las inserciones serán realizadas por el nodo referencia por 1c (final de la cola), y la extracción por el nodo siguiente a lc (último de la cola). Conseguimos que con un único puntero se pueda acceder al final y al frente de la cola. 1.3. BICOLAS La estructura bicola o cola de doble entrada se puede considerar como una variación del TDA cola. Es un conjunto ordinario de elementos del cual se pueden añadir o quitar elementos desde cualquier extremo de la bicola; el acceso a la bicola está permitido desde los dos extremos, es una cola bidireccional. Identificamos sus extremos como izquierdo y derecho respectivamente. Las operaciones básicas de las de las bicolas son: Crear bicola: inicializa la bicola como vacía. Es la primera operación a realizar en una bicola. Borrar bicola: elimina todos los elementos de la bicola. Insertar izquierda: añade un elemento por el extremo izquierdo de la bicola. Insertar derecha: añade un elemento por el extremo derecho de la bicola. Eliminar izquierda: extrae el elemento del extremo izquierdo de la bicola. Eliminar derecha: extrae el elemento del extremo derecho de la bicola. Bicola vacía: comprueba si la bicola no tiene elementos, devolviendo verdadero si no los tiene. 7 Ampliación de informática TDA Cola Bicola llena: comprueba si la bicola está llena de elementos, devolviendo verdadero si lo está. Tamaño de la bicola: devuelve el número máximo de elementos que puede contener la bicola. Al tipo de dato bicola se le puede poner restricciones respecto al tipo de entrada o al de salida. Una bicola con restricción de entrada es aquella que sólo permite inserciones por uno de los dos extremos, pero se pueden extraer elementos por los dos. Una bicola con restricción de salida es aquella que permite inserciones por los dos extremos, pero sólo permite extraer elementos por uno de los dos. 8 Ampliación de informática TDA Cola 2. UTILIDADES DEL TDA COLA El ámbito de utilización de las colas es muy amplio, desde el control del proceso de tareas en un sistema operativo hasta simulaciones del sistema de control aéreo en un aeropuerto. En general, son útiles cuando la aplicación requiera del orden estricto de entrada de los datos. Aseguran un tratamiento justo de los objetos que contienen, ya que siempre se extraerá el elemento que más tiempo lleva esperando. El estudio de las colas es importante porque proporciona tanto una base teórica del tipo de servicio que podemos esperar de un determinado recurso, como la forma en la cual dicho recurso puede ser diseñado para proporcionar un determinado grado de servicio a sus clientes. Algunas de sus utilidades son: o En los sistemas operativos se usan para planificar el uso de los distintos recursos de un ordenador. Uno de estos recursos es la propia CPU. Si se está trabajando en un sistema multiusuario, cuando se le dice al ordenador que ejecute un programa concreto, el sistema operativo añade la petición a su “cola de trabajo”. Cuando su petición llega al frente de la cola, el programa solicitado pasa a ejecutarse. o Colas de impresión: cuando se intentan imprimir varios documentos a la vez o la impresora está ocupada, los trabajos se almacenan en una cola según el orden de llegada. o En la teoría de grafos se usan para buscar un elemento en un grafo (con la intención de saber si existe, de agregar un elemento en determinado orden o cualquier otro propósito), necesitamos recorrerlo. Para ello existen dos algoritmos: el recorrido en profundidad y el recorrido en anchura. Para el recorrido en anchura tendremos una cola de nodos visitados. Cada vez que se visite un nodo, lo metemos en la cola, de modo que cuando terminemos de visitar todos los nodos adyacentes al nodo de partida, comencemos a analizar los nodos adyacentes a cada uno de los nodos visitados. Tras analizar todos los nodos y sus adyacencias, se pasa al nodo que sigue en la lista al de partida, y si no está visitado, se visita también. En caso de estar visitado, se pasa al siguiente y así hasta que se termine la lista de nodos. o En contabilidad se usan para registrar el valor de un inventario. Su uso es apropiado cuando se cuenta con varios lotes de un mismo producto. Este método presume que, a los efectos del cálculo del costo, el artículo que se va a sacar del almacén es el más antiguo de su clase. o Simulación por ordenador de una situación en el mundo real, como por ejemplo el comportamiento de una cola de clientes en un supermercado, de coches esperando en una calle ante un semáforo en rojo, de llamadas telefónicas recibidas en una centralita esperando hasta obtener línea libre hacia una determinada extensión o el tiempo de espera para ser servidos en un autocine, (ejemplo que ampliaremos después). Los clientes que forman estas colas son atendidos considerando que el primero que llega es el primero en ser atendido. Dado este escenario, habitualmente estamos interesados en determinar la distribución de la longitud de la cola y de los tiempos de espera de los clientes, y la eficiencia del servidor. Ese es el objetivo de un programa de simulación. 9 Ampliación de informática TDA Cola 2.1. SIMULACIÓN Antes de que los astronautas fueran al espacio, gastaron muchas horas en un simulador de vuelo espacial, un modelo físico de un vehículo espacial en el que los astronautas podían experimentar todas las cosas que sucederían en el espacio. Este simulador de vuelo espacial es un modelo físico de otro objeto. La técnica que usaban se llamaba simulación. En informática, usamos la misma técnica para construir modelos computacionales de objetos y sucesos en vez de modelos físicos. Un modelo puede verse como una serie de sentencias o reglas que describen el comportamiento de un sistema del mundo real. Cambiamos las reglas y vemos el efecto de estos cambios en el comportamiento de lo que estamos observando. En una simulación por ordenador, cada objeto del sistema del mundo real se representa normalmente como un objeto de datos. Las acciones del mundo real se representan como operaciones sobre los objetos de datos. Las reglas que describen el comportamiento determinan qué acciones deben realizarse. Veamos un tipo muy útil de simulación que utiliza colas como la estructura de datos básica. De hecho, el sistema del mundo real se llama sistema de cola. Un sistema de cola está formado por servidores y colas de objetos a servir. El comportamiento que examinamos es el tiempo de espera. En su forma más simple, un sistema de colas consiste en un único servidor que atiende una única cola, pero es fácil extender esta idea a escenarios más complicados, como por ejemplo: 10 Ampliación de informática TDA Cola Los objetivos de un sistema de cola son utilizar a los servidores tan completamente como sea posible y mantener el tiempo de espera dentro de unos límites razonables. Estos objetivos necesitan normalmente de un compromiso entre coste y satisfacción del cliente. Digamos que a un nivel personal ¡a nadie le gusta esperar en una cola! Si hubiera una cajera para cada cliente en el supermercado, el cliente estaría encantado. Sin embargo, el supermercado, no duraría como negocio mucho tiempo. Por tanto, hay que llegar a un compromiso: el número de cajeras debe estar dentro del presupuesto del comercio y el cliente no debe esperar, por término medio, demasiado tiempo. Una simulación por computadora es una forma de examinar este compromiso. Para hacer una simulación por computadora de un sistema de cola, hay cuatro cosas que necesitamos saber: El número de sucesos y cómo afectan al sistema. El número de servidores. La distribución de los tiempos de llegada. El tiempo de servicio esperado. El programa utiliza estos parámetros para predecir el tiempo medio de espera. Las interacciones de estos parámetros son las reglas del modelo. Cambiando estos parámetros, cambiamos las reglas. Los tiempos medios de espera se examinan luego para determinar cuál podría ser un compromiso razonable. Ejemplo: consideramos el caso de un autocine. Supongamos que existe un cajero en el autocine y la transacción media necesita 5 minutos. ¿Cuál es el tiempo de medio de espera de un coche? Si el negocio va bien y los coches llegan más frecuentemente, ¿qué efecto tiene esto en el tiempo medio de espera? ¿Cuándo será necesario abrir una segunda ventanilla? Este problema es claramente un problema de colas. Tenemos un servidor (el cajero) y objetos a ser servidos (el cliente o el coche, dependiendo de cómo queramos ver el proceso) y estamos interesados en observar el tiempo medio de espera. Determinemos los parámetros para simular estas operaciones de un cajero. Los sucesos son las llegadas y salidas de los clientes o coches. Debido a que la gente llega y sale en coche, pensemos en los coches como los objetos. El número de servidores es 1. La distribución de los tiempos de llegada es “aproximadamente cada 5 minutos”. Podemos cuantificar esta cantidad usando probabilidades. Decir que la probabilidad de llegada de un coche en cada minuto es 0.20 seria lo mismo que tener intervalos de tiempo de un minuto. Queremos poner la distribución en minutos porque calcularemos el tiempo medio de espera en minutos. Entonces el tiempo de servicio esperado es el tiempo de transacción media, el cual es 5 minutos. Resolveremos este problema como una simulación conducida por el tiempo. Una simulación conducida por el tiempo es aquella en la que el programa tiene un contador que representa a un reloj. 11 Ampliación de informática TDA Cola Cada vez que se incrementa el contador, pasa un minuto. Las cosas que pueden suceder cada minuto y que deben almacenarse son: puede llegar un coche, puede salir un coche, la gente puede estar aún esperando en la cola. Hagamos una lista de estas acciones y lo que habría que hacer cuando ocurran: - Cuando llega un coche, ponerlo en la cola. Si el cajero está libre, avanza el coche a la ventanilla. El tiempo de servicio se pone en 5 minutos. Si hay un cliente en la ventanilla, el tiempo que le queda a ese cliente para estar servido debe decrementarse. Si hay coches en la cola, debe registrarse que tienen que permanecer en la cola 1 minuto más. ¿Cómo sabemos si ha llegado o no un coche? Hemos convertido nuestro “aproximadamente cada 5 minutos” a “la probabilidad de llegada de un coche cada minuto es 0.20”. Debido a que cada incremento de nuestro reloj representa un minuto, podemos simular la llegada de un cliente utilizando un generador de números aleatorios. Podemos simular la llegada de un coche generando un número aleatorio entre 0.0 y 1.0 cada minuto y aplicando las siguientes reglas: 1. Si el número aleatorio está entre 0.0 y 0.2, ha llegado un coche. 2. Si el número aleatorio está entre 0.2 y 1.0, no ha llegado ningún coche. Si llega un coche, se pone en la cola. Podemos simular el que el cajero esté libre, considerando que estará libre cuando el tiempo que le queda a un coche de la ventanilla es 0. Para mover un coche a la ventanilla, simplemente quitamos el primer coche de la cola e inicializamos el tiempo que le queda para ser servido a 5, el tiempo de servicio. Si un cliente está en la ventanilla, el tiempo que le queda para terminar el servicio será distinto de 0 y lo decrementamos en 1. Observe que el tiempo necesario para el servicio puede ser ahora 0. Si es así, se considerará que el cajero está libre en el siguiente intervalo de minuto. Ahora que comprendemos las acciones, podemos diseñar la presentación de los objetos. Podemos representar al cajero como una variable, la cual se pone a 5 cuando se mueve un coche hacia la caja y se decrementa en 1 cada minuto que el coche permanece allí. Cuando este contador llega a 0, el cajero está libre. ¿Qué necesitamos conocer acerca de cada coche? Sólo cuanto tiempo ha estado esperando. Por tanto, cada coche puede representarse por un contador entero. Este contador se pone a cero cuando entra un coche en la cola y se incrementa por cada minuto que permanece allí. Para encontrar el tiempo medio de espera, debemos contar el número de coches que han sido servidos y el tiempo de espera total para todos los coches. Hemos descrito el problema en términos de una relación de llegada específica y tiempo de servicio. Realmente estos valores variarán para ver qué efectos tienen los cambios sobre el tiempo de espera medio. Por tanto, la probabilidad de llegada de un coche en cada minuto y el tiempo medio de transacción se leerán como entrada, junto con el número de 5 minutos que debe durar la simulación. En una simulación conducida por el tiempo, los parámetros pueden variar, pero los sucesos están determinados por el reloj, y (normalmente) por un generador de simulación de números aleatorios. En contraste, una simulación conducida por sucesos 12 Ampliación de informática TDA Cola es una simulación en la que las operaciones sobre los objetos, los sucesos, se leen como datos de entrada. 2.2. COLAS DE PRIORIDADES Son un tipo de colas, en las que el servicio no se proporciona únicamente aplicando el concepto de cola (primero en llegar, primero en ser servido), sino que cada persona tiene asociada una prioridad basada en un criterio objetivo, de tal forma que a la hora de sacar un elemento de la cola, saco el del frente, y a la hora de insertar un elemento en la cola, tendré en cuenta la prioridad del elemento que quiero insertar, y para ello se inserta en la cola por orden de prioridad, y si hay más elementos que tienen la misma prioridad que el que queremos insertar, los procesamos según su orden de llegada, es decir, que lo colocamos como el último de los elementos con esa prioridad. 2.3. MONTÍCULOS Un montículo es una estructura de datos interesante que puede ser implementada muy efectivamente con un árbol binario almacenado en un array. Pero antes de hablar acerca de las propiedades especiales de esta estructura, necesitamos hablar un poco sobre la forma de un árbol binario. Un árbol binario lleno es un árbol binario en el que todas las hojas están al mismo nivel, y cada nodo que no es hoja tiene dos hijos. La figura básica de un árbol binario lleno es triangular. Un árbol binario completo es un árbol binario que está lleno hasta el penúltimo nivel, con las hojas del último nivel tan a la izquierda como sea posible. Un montículo es una estructura de datos que satisface dos propiedades, una concerniente a su figura y otra concerniente al orden de sus elementos. La propiedad sobre la figura es sencilla: un montículo debe ser un árbol binario completo. La propiedad sobre el orden dice que, para cada nodo del montículo, el valor almacenado en ese nodo es mayor o igual que el valor de cada uno de sus hijos. En la discusión de las aplicaciones de cola dijimos que el sistema operativo de un ordenador multiusuario puede usar trabajo en colas para guardar peticiones de los usuarios en el orden en el que son hechas. Otra forma de manejar tales peticiones es atendiendo a la importancia del pedido. Es decir, el jefe de la compañía puede obtener mayor prioridad que el programador más principiante. O un programa interactivo puede obtener mayor prioridad que un “trabajo en lote” para imprimir un informe que no se necesita hasta el día siguiente. Para manejar estas peticiones eficientemente, el sistema operativo puede usar una cola de prioridades, en las cuales el orden de proceso es esencial. Como un montículo nos da acceso muy rápido al elemento mayor, en la estructura, es una buena forma para implementar una cola de prioridades. Los montículos son también útiles en la ordenación. 13 Ampliación de informática TDA Cola 3. IMPLEMENTACIÓN EN C MEDIANTE LISTAS ENLAZADAS #include <stdio.h> #include <stdlib.h> #include <string.h> /*declaracion de tipos*/ struct NODE { int info; struct NODE *sgte; }; typedef struct NODE nodo; typedef struct NODE *posicion; typedef struct { int longitud; posicion prim,ult; }COLA; /*subprograma que obtiene memoria para poder almacenar un nodo*/ posicion obtener_nodos() { static posicion nodo_temporal2; nodo_temporal2=(posicion)malloc(1*sizeof(nodo)); if (nodo_temporal2==NULL) printf("ERROR, no se ha podido reservar la memoria requerida \n"); return nodo_temporal2; } /*subprograma que libera la memoria requerida para almacenar un nodo*/ int liberar_nodos(nodo_temporal2) posicion nodo_temporal2; { free((void *)nodo_temporal2); return 1; } /*subprograma que devuelve el tamaño de una cola, es decir, su numero de elementos*/ int tamagno(cola4) COLA cola4; { int tamagno_real; tamagno_real=cola4.longitud; return tamagno_real; } /*subprograma que decide si una cola esta o no vacia mirando su tamaño*/ int vacia(cola4) COLA cola4; 14 Ampliación de informática TDA Cola { int respuesta3; if (tamagno(cola4)==0) respuesta3=1; else respuesta3=0; return respuesta3; } /*subprograma que decide si una cola esta o no llena, es decir, si queda memoria en el ordenador para seguir aumentando el tamaño de la cola*/ int llena(cola4) COLA cola4; { int respuesta3; if (obtener_nodos()==NULL) respuesta3=1; else respuesta3=0; return respuesta3; } /*subprograma que decide si la posicion dada es la siguiente al ultimo elemento de la cola*/ int final(cola4,posicion5) COLA cola4; posicion posicion5; { int respuesta3; if (posicion5==NULL) respuesta3=1; else respuesta3=0; return respuesta3; } /*subprograma que hace que posicion de la cola*/ int primero(cola4,posicion3) COLA cola4; posicion *posicion3; { int error1; posicion3 apunte a la primera if (vacia(cola4)==0) { *posicion3=cola4.prim; error1=0; } else { error1=1; printf("ERROR, la cola esta vacia y por tanto no hay primer elemento \n"); } 15 Ampliación de informática TDA Cola return error1; } /*subprograma que hace posicion4 apunte a la posicion siguiente a posicion3 en la cola*/ int siguiente (cola3,posicion3,posicion4) COLA cola3; posicion posicion3,*posicion4; { int error1; if (vacia(cola3)==0) { if (final(cola3,posicion3)==0) { *posicion4=posicion3->sgte; error1=0; } else { printf("ERROR en el subprograma siguiente, pues se esta intentando acceder a una posicion inexistente \n"); error1=1; } } else { printf("ERROR, la cola esta vacia y por tanto no se puede acceder a la siguiente posicion de la cola \n"); error1=1; } return error1; } /*subprograma que muestra el elemento de la cola correspondiente a la posicion dada*/ int contenido(cola2,posicion3,elemento3) COLA cola2; posicion posicion3; int *elemento3; { int error1; if (final(cola2,posicion3)==0) { *elemento3=posicion3->info; error1=0; } else { printf("ERROR en el subprograma contenido, pues intentando acceder a una posicion inexistente \n"); error1=1; } return error1; } /*subprograma que crea una cola vacia*/ int crear_cola(cola2) COLA *cola2; { 16 se esta Ampliación de informática TDA Cola cola2->longitud=0; cola2->prim=NULL; cola2->ult=NULL; return 1; } /*subprograma que borra todos los elementos de la cola liberando ademas toda la memoria requerida para estos*/ int borrar_cola(cola2) COLA *cola2; { posicion posicion1,posicion2; int OK; if (vacia(*cola2)==0) { primero(*cola2,&posicion1); final(*cola2,posicion1); do { posicion2=posicion1; siguiente(*cola2,posicion1,&posicion1); liberar_nodos(posicion2); } while(final(*cola2,posicion1)==0); cola2->longitud=0; cola2->prim=NULL; cola2->ult=NULL; OK=1; } return OK; } /*subprograma que inserta el elemento dado en el final de la cola*/ int queue(cola3,elemento2) COLA *cola3; int elemento2; { posicion nodo_temporal1; int respuesta2; if (llena(*cola3)==1) { printf("ERROR, la cola esta llena y por tanto no se puede insertar ningun elemento \n"); respuesta2=0; } else { nodo_temporal1=obtener_nodos(); nodo_temporal1->info=elemento2; nodo_temporal1->sgte=NULL; if (vacia(*cola3)==1) { cola3->prim=nodo_temporal1; respuesta2=1; } 17 Ampliación de informática TDA Cola else { (cola3->ult)->sgte=nodo_temporal1; respuesta2=1; } cola3->ult=nodo_temporal1; cola3->longitud=(cola3->longitud)+1; } return respuesta2; } /*subprograma que elimina el primer elemento de la cola*/ int dequeue(cola3,elemento2) COLA *cola3; int *elemento2; { posicion nodo_temporal1; int respuesta2; if (vacia(*cola3)==1) { printf("ERROR, la cola esta vacia y por tanto no se puede eliminar ningun elemento \n"); respuesta2=0; } else { nodo_temporal1=cola3->prim; *elemento2=nodo_temporal1->info; if (tamagno(*cola3)==1) cola3->ult=NULL; cola3->prim=nodo_temporal1->sgte; liberar_nodos(nodo_temporal1); cola3->longitud=(cola3->longitud)-1; respuesta2=1; } return respuesta2; } /*subprograma que muestra el contenido de la cola, es decir, todos los elementos que posee*/ int mostrar_cola(cola2) COLA cola2; { int elemento2,respuesta2; posicion posicion1; if (vacia(cola2)==1) { printf("ERROR, la cola esta vacia y por tanto no se puede mostrar \n"); respuesta2=0; } else { primero(cola2,&posicion1); 18 Ampliación de informática TDA Cola printf("la cola tras las modificaciones realizadas quedaria de la siguiente manera \n"); do { contenido(cola2,posicion1,&elemento2); printf("%d",elemento2); siguiente(cola2,posicion1,&posicion1); if (final(cola2,posicion1)==0) { printf(" ->"); respuesta2=0; } else { printf("\n"); respuesta2=1; } } while(respuesta2==0); } return respuesta2; } /*subprograma que guarda el numero de elementos y los elementos de la cola dada en el fichero indicado*/ int guardar_cola_fichero(cola2,nombre_fichero3) COLA cola2; char nombre_fichero3[20]; { int elemento2,respuesta2; FILE *in; posicion posicion1; in=fopen(nombre_fichero3,"w"); if (in!=NULL) { if (vacia(cola2)==1) { printf("ERROR, la cola esta vacia y por tanto no se puede guardar en un fichero \n"); respuesta2=0; } else { fprintf(in,"%d",cola2.longitud); fprintf(in,"\n"); primero(cola2,&posicion1); do { contenido(cola2,posicion1,&elemento2); fprintf(in,"%d",elemento2); fprintf(in,"\n"); siguiente(cola2,posicion1,&posicion1); } while(final(cola2,posicion1)==0); respuesta2=1; } 19 Ampliación de informática TDA Cola fclose(in); } else { printf("ERROR en la creacion del fichero para guardar la cola \n"); respuesta2=0; } return respuesta2; } /*subprograma que lee el numero de elementos y los elementos de una cola guardada en el fichero dado*/ int leer_cola_fichero(nombre_fichero3,cola2) COLA *cola2; char nombre_fichero3[20]; { int j,numero_elementos_cola,elemento2,respuesta2; FILE *in; in=fopen(nombre_fichero3,"r"); if (in!=NULL) { fscanf(in,"%d",&numero_elementos_cola); j=0; while (j<numero_elementos_cola) { fscanf(in,"%d",&elemento2); queue(cola2,elemento2); j=j+1; } respuesta2=1; fclose(in); } else { printf("ERROR en la lectura del fichero para obtener la cola \n"); respuesta2=0; } return respuesta2; } /*subprograma que va pidiendo al usuario el numero de elementos y los elementos de una cola a crear*/ int leer_cola_teclado(cola2) COLA *cola2; { int i,elemento2,numero_elementos_cola; printf("por favor introduzca el numero de elementos que quiere que tenga la cola inicialmente \n"); scanf("%d",&numero_elementos_cola); for (i=1;i<=numero_elementos_cola;i++) { printf("por favor introduzca el elemento \n",i); scanf("%d",&elemento2); queue(cola2,elemento2); 20 %d de la cola Ampliación de informática TDA Cola } return 1; } /*programa principal que va preguntando al usuario el tipo de opciones que desea realizar y si quiere repetir alguna*/ main() { COLA cola1; int elemento1,opcion,respuesta1,OK1,OK2,OK3; char nombre_fichero1[20],nombre_fichero2[20]; respuesta1=1; OK1=0; OK2=0; OK3=0; do { printf("por favor seleccione la opcion que desee realizar \n"); printf("1= leer cola de fichero, 2= leer cola de teclado, 3= guardar cola en un fichero, 4= insertar un elemento, 5= eliminar un elemento, 6= borrar cola, 7= mostrar cola, 8= SALIR \n"); scanf("%d",&opcion); while((opcion<1)||(opcion>8)) { printf("ERROR, ha introducido un numero no valido \n"); printf("por favor seleccione la opcion que desee realizar \n"); printf("1= leer cola de fichero, 2= leer cola de teclado, 3= guardar cola en un fichero, 4= insertar un elemento, 5= eliminar un elemento, 6= borrar cola, 7= mostrar cola, 8=SALIR \n"); scanf("%d",&opcion); } switch(opcion) { case 1: printf("por favor introduzca el nombre del fichero, con la extension, de donde quiere leer la cola \n"); scanf("%s",nombre_fichero1); OK1=crear_cola(&cola1); OK2=leer_cola_fichero(nombre_fichero1,&cola1); break; case 2: OK1=crear_cola(&cola1); OK3=leer_cola_teclado(&cola1); break; case 3: if ((OK1==1)||(OK2==1)||(OK3==1)) { printf("por favor introduzca el nombre del fichero, con la extension, de donde quiere guardar la cola \n"); scanf("%s",nombre_fichero2); guardar_cola_fichero(cola1,nombre_fichero2); } else printf("para poder guardar una cola en un fichero primero hay que obtener una cola \n"); break; case 4: if ((OK1==1)||(OK2==1)||(OK3==1)) { 21 Ampliación de informática TDA Cola printf("por favor introduzca el elemento que quiere insertar en la cola \n"); scanf("%d",&elemento1); queue(&cola1,elemento1); } else printf("para poder insertar un elemento en la cola primero hay que obtener una cola \n"); break; case 5: if ((OK1==1)||(OK2==1)||(OK3==1)) { if (dequeue(&cola1,&elemento1)==1) printf("el elemento que se ha eliminado de la cola ha sido %d \n", elemento1); } else printf("para poder eliminar un elemento de la cola primero hay que obtener una cola \n"); break; case 6: if ((OK1==1)||(OK2==1)||(OK3==1)) { borrar_cola(&cola1); printf("la operacion de borrar_cola ha sido realizada con exito \n"); } else printf("para poder borrar una cola primero hay que obtener una cola \n"); break; case 7: if ((OK1==1)||(OK2==1)||(OK3==1)) { mostrar_cola(cola1); } else printf("para poder mostrar una cola primero hay que obtener una cola \n"); break; case 8: break; } printf("desea ejecutar alguna otra opcion? \n"); printf("1= SI, 2= NO \n"); scanf("%d",&respuesta1); while((respuesta1<1)||(respuesta1>2)) { printf("ERROR, ha introducido un numero no valido \n"); printf("desea ejecutar alguna otra opcion? \n"); printf("1= SI, 2= NO \n"); scanf("%d",&respuesta1); } } while(respuesta1!=2); } 22 Ampliación de informática TDA Cola 4. BIBLIOGRAFÍA http://www.monografias.com/trabajos25/colas/colas.shtml http://www.jorgesanchez.net/programacion/dinamicas.pdf http://es.wikipedia.org http://webdiis.unizar.es/~jcampos/EDA/material/ejemplos_aplicacion_colas.pdf http://www.cucea.udg.mx/servicios/cdrive/archivos/fram2.doc http://www.algoritmia.net http://ce.azc.uam.mx/profesores/franz/omi/monticulo.html http://www.guajara.com/wiki/es/wikipedia/c/co/cola_programacion_.html http://www.infor.uva.es/~belar/Ampliacion_Informatica.htm Pascal y estructuras de datos. Nell Dale y Susan C. Lilly. Editorial Mc Graw Hill, 1989 Algoritmos y estructuras de datos, una perspectiva en C. Luis Joyanes Aguilar, Ignacio Zahonero Martínez, editorial Mc Graw Hill, 2004 23 Ampliación de informática TDA Cola 24