Una cola (también llamada fila) es un tipo de dato abstracto, caracterizada por ser una secuencia de elementos en la que la operación de inserción push se realiza por un extremo y la operación de extracción pull por el otro. También se le llama estructura FIFO (del inglés First In First Out), debido a que el primer elemento en entrar será también el primero en salir.
Las colas se utilizan en sistemas informáticos, transportes y operaciones de investigación (entre otros), donde los objetos, personas o eventos son tomados como datos que se almacenan y se guardan mediante colas para su posterior procesamiento.
Este tipo de estructura de datos abstracta se implementa en lenguajes orientados a objetos mediante clases, en forma de listas enlazadas.
Usos concretos de la cola
La particularidad de una cola es el hecho de que solo podemos acceder al primer y al último elemento de la estructura. Así mismo, los elementos solo se pueden eliminar por el principio y solo se pueden añadir por el final de la cola.
Ejemplo de Cola
Ejemplos de colas en la vida real serían: personas comprando en un supermercado, esperando para entrar a ver un partido de béisbol, esperando en el cine para ver una película, una pequeña peluquería, etc. La idea esencial es que son todos líneas de espera.
Información adicional
En caso de estar vacía, borrar un elemento sería imposible hasta que no se añade un nuevo elemento.
A la hora de añadir un elemento podríamos darle una mayor importancia a unos elementos que a otros (un cargo VIP) y para ello se crea un tipo de cola especial que es la cola de prioridad. (Ver cola de prioridad).
Operaciones Básicas
Crear: se crea la cola vacía.
Encolar: se añade un elemento a la cola. Se añade al final de esta.
Desencolar: (sacar, salir, eliminar): se elimina el elemento frontal de la cola, es decir, el primer elemento que entró.
Frente: (consultar, front): se devuelve el elemento frontal de la cola, es decir, el primer elemento que entró.
Implementaciones
Las colas pueden implementarse utilizando Listas Enlazadas o utilizando una variación del arreglo conocido comúnmente como una cola circular. La ventaja de la cola circular es que se puede utilizar memoria contigua en RAM que permite mejor desempeño del caché que en una lista enlazada además de un menor uso de RAM. Estas pueden crecer dinámicamente o no.
Colas en C
#include<stdio.h>#include<stdlib.h>#define RED "\x1B[31m"#define GRN "\x1B[32m´´#define YEL "\x1B[33m"#define BLU "\x1B[34m"#define MAG "\x1B[35m"#define CYN "\x1B[36m"#define WHT "\x1B[37m"#define RESET "\x1B[0m"typedefstructNode{structNode*next;structNode*previous;char*data;}node_t;typedefstructQueue{node_t*top;node_t*bottom;intsize;}queue_t;node_t*createNode(char*);char*removeNode(node_t*);queue_t*createQueue();intremoveQueue(queue_t*);char*peek(queue_t*);intisEmpty(queue_t*);/* Si manejaramos una Queue estática...int isFull(queue_t *);*/intenqueue(char*,queue_t*);char*dequeue(queue_t*);intprintQueue(queue_t*);intprintNode(node_t*);intgetQueueSize(queue_t*);node_t*createNode(char*data){node_t*node=(node_t*)calloc(1,sizeof(node_t));node->data=data;returnnode;}char*removeNode(node_t*node){char*data=NULL;if(node){if(node->previous)node->previous->next=node->next;if(node->next)node->next->previous=node->previous;data=node->data;free(node);}returndata;}queue_t*createQueue(){queue_t*queue=(queue_t*)calloc(1,sizeof(queue_t));returnqueue;}intremoveQueue(queue_t*queue){if(queue){node_t*ptr=queue->top;node_t*aux;while(ptr!=NULL){aux=ptr;ptr=ptr->next;free(removeNode(aux));}free(queue);}return(queue==NULL);}char*peek(queue_t*queue){if(queue&&queue->top!=NULL){returnqueue->top->data;}returnNULL;}intisEmpty(queue_t*queue){return(queue->top==NULL);}intenqueue(char*data,queue_t*queue){if(queue!=NULL){node_t*new=createNode(data);if(queue->bottom==NULL){queue->bottom=new;queue->top=new;//queue->top->previous = queue->bottom;//No need to set previous for bottom since calloc makes it null.}else{queue->bottom->next=new;new->previous=queue->bottom;new->next=NULL;queue->bottom=new;}queue->size++;returnEXIT_SUCCESS;}returnEXIT_FAILURE;}char*dequeue(queue_t*queue){if(queue!=NULL&&queue->top!=NULL){char*data;node_t*aux=queue->top;queue->top=aux->next;queue->top->previous=NULL;data=removeNode(aux);queue->size--;returndata;}returnNULL;}intprintQueue(queue_t*queue){node_t*ptr=queue->top;inti,size=getQueueSize(queue);for(i=0;i<size;i++){#ifdef __unix__printf(GRN"[%i]Address: %p, Data: %s, Next: %p, Previous: %p\n"RESET,i,ptr,ptr->data,ptr->next,ptr->previous);#elif __WIN32printf("[%i]Address: %p, Data: %s, Next: %p, Previous: %p\n",i,ptr,ptr->data,ptr->next,ptr->previous);#endifptr=ptr->next;}printf("\n");returnEXIT_SUCCESS;}intprintNode(node_t*ptr){char*i="printNode function";#ifdef __unix__printf(GRN"[%s]Address: %p, Data: %s, Next: %p, Previous: %p\n"RESET,i,ptr,ptr->data,ptr->next,ptr->previous);#elif __WIN32printf("[%s]Address: %p, Data: %s, Next: %p, Previous: %p\n",i,ptr,ptr->data,ptr->next,ptr->previous);#endifprintf("\n");returnEXIT_SUCCESS;}intgetQueueSize(queue_t*queue){returnqueue->size;}
Colas en Pascal
Clase PscColas, Matriz[]:Cadena, Posición, Valor:EnteroPrivado:
Proc Comenzar
ReDim Matriz,1
Posición = 0
Valor = 0
FinProcProc Terminar
Borrar Matriz
FinProcProc Longitud:EnteroDevolver Límite(Matriz)
FinProcProc ReDimensionarLaCola
ReDim Preservar Matriz, LongMat(Matriz) + 1
FinProcPúblico:
Proc Encolar(Contenido:Cadena)
Si Posición = LongMat(Matriz) Entonces ReDimensionarLaCola
Matriz[Posición] = Contenido
Posición = Posición + 1
FinProcProc DesEncolar
Si Neg(Valor >= Límite(Matriz)) Entonces Valor = Valor + 1
FinProcProc FrenteCola:Cadena
Devolver Matriz[Valor]
FinProcProc FondoCola:CadenaDevolver Matriz[Límite(Matriz)]
FinProcProp ColaLongitud:EnteroLec:Longitud
FinPropPrivado:
Constructor: Comenzar
Destructor: Terminar
FinClase
Colas en Maude
La ColaNV es la cola no vacía, que diferenciamos de la cola normal a la hora de tomar en cuenta errores. A su vez, el elemento X representa el tipo de valor que puede contener la cola: entero, carácter, registro....
fmod COLA {X :: TRIV} is
sorts ColaNV{X} Cola{X} .
subsort ColaNV{X} < Cola{X} .
*** generadores
op crear : -> Cola{X} [ctor] .
op encolar : X$Elt Cola{X} -> ColaNV {X} [ctor] .
*** constructores
op desencolar : Cola{X} -> Cola{X} .
*** selectores
op frente : ColaNV{X} -> X$Elt .
*** variables
var C : ColaNV{X} .
vars E E2 : X$Elt .
*** ecuaciones
eq desencolar(crear) = crear .
eq desencolar(encolar(E, crear)) = crear .
eq desencolar(encolar(E, C)) = encolar(E, desencolar(C)) .
eq frente(encolar(E, crear)) = E .
eq frente(encolar(E, C)) = frente(C) .
endfm
Especificación de una cola de colas de enteros en Maude:
view VInt from TRIV to INT is
sort Elt to Int .
endv
view VColaInt from TRIV to COLA{VInt} is
sort Elt to Cola{VInt} .
endv
fmod COLA-COLAS-INT is
protecting INT .
protecting COLA{VColaInt} .
*** operaciones propias de la cola de colas de enteros
op encolarInt : Int ColaNV{VColaInt} -> ColaNV{VColaInt} .
op desencolarInt : Cola{VColaInt} -> Cola{VColaInt} .
op frenteInt : ColaNV{VColaInt} -> [Int] .
*** variables
var CCNV : ColaNV{VColaInt} .
var CC : Cola{VColaInt} .
var CE : Cola{VInt} .
var E : Int .
*** ecuaciones
eq encolarInt(E, encolar(CE, CC)) = encolar(encolar(E, CE), CC) .
eq desencolarInt (encolar(CE, crear)) = encolar(desencolar(CE), crear) .
eq desencolarInt (encolar(CE, CCNV)) = encolar(CE, desencolarInt(CCNV)) .
eq frenteInt(CCNV) = frente(frente(CCNV)) .
endfm
Colas en C++
#ifndef COLA#define COLA // Define la colausingnamespacestd;template<classT>classCola{structNodo{Telemento;structNodo*siguiente;// coloca el nodo en la segunda posición};Nodo*primero;Nodo*ultimo;unsignedintelementos;public:Cola():primero(0),ultimo(0),elementos(0){}~Cola(){while(elementos!=0)pop();}voidpush(constT&elem){Nodo*aux=newNodo;aux->elemento=elem;if(elementos==0)primero=aux;elseultimo->siguiente=aux;ultimo=aux;++elementos;}voidpop(){Nodo*aux=primero;primero=primero->siguiente;if(ultimo==aux){ultimo=primero;}deleteaux;--elementos;}Tconsultar()const{returnprimero->elemento;}boolvacio()const{returnelementos==0;}
Colas en JAVA
Al igual que las pilas, este tipo de estructura de datos se puede implementar de forma estática o dinámica, es decir, ya sea con un arreglo o con una lista enlazada. Al hablar de una cola estática, se considera que tendrá un tamaño definido y no podrá superar dicha capacidad para el almacenamiento de más información, solo la indicada. Y con respecto a una cola dinámica corresponde a aquella que no tendrá un límite de capacidad, es decir, podemos hacer n número de inserciones.
A continuación se presenta la Cola estática, la cual es implementada basándose en un arreglo:
publicclassColaEstatica{privateintcola[];privateinttop;//indica la posición del último elemento insertadoprivateintcapacidad;publicColaEstatica(intcap){capacidad=cap;cola=newint[capacidad];top=-1;}publicbooleanestaVacia(){return(top==-1);}publicbooleanestaLlena(){return((top+1)==capacidad);}publicvoidencolar(intelemento){if(estaLlena()==false)cola[++top]=elemento;elseSystem.out.println("Desbordamiento superior, no se puede encolar");}publicintdesencolar(){if(estaVacia()==false){intdato=cola[0];top--;for(inti=0;i<=top;i++){cola[i]=cola[i+1];}returndato;}else{System.out.println("Desbordamiento inferior, no se puede desencolar");}return-1;}publicstaticvoidmain(Stringargs[]){ColaEstaticacolita=newColaEstatica(5);colita.encolar(1);colita.encolar(12);colita.encolar(3);intr=colita.desencolar();System.out.println("El dato eliminado es "+r);booleanb=colita.estaVacia();booleanc=colita.estaLlena();System.out.println("¿Está vacia la pla? "+b);System.out.println("¿Está llena la pla? "+c);}}
Enseguida se presenta la implementación de la Cola de forma dinámica, implementada con base en una lista simplemente enlazada:
classNodo{intinformacion;Nodosiguiente;publicNodo(itninfo){informacion=info;siguiente=null;}}classCola{NodonodoCabeza,nodoFinal;publicCola(){// Inicializa la Cola, en este caso su primer estado es vacíanodoCabeza=null;nodoFinal=null;}publicvoidinsertar(intx){Nodonuevo=newNodo(x);if(nodoCabeza==null&&nodoFinal==null){NodoCabeza=nuevo;}else{nodoFinal.siguiente=nuevo;}nodoFinal=Nuevo;}publicinteliminar(){if(nodoCabeza==null&&nodoFinal==null){System.out.println("Cola vacía, no se puede eliminar");}else{NodonodoEliminado=nodoCabeza;nodoCabeza=nodoCabeza.siguiente;nodoEliminado.siguiente=null;returnnodoEliminado.informacion;}}publicvoidimprimirCola(){ifnodoCabeza==null&&nodoFinal==null){System.out.println("Cola vacía");}else{for(Nodoauxiliar=nodoCabeza;auxiliar!=null;auxiliar=auxiliar.siguiente){System.out.print(auxiliar.informacion+" ");}System.out.println();}}publicstaticvoidmain(String[]ar){Colacola=newCola();cola.insertar(8);cola.insertar(25);cola.insertar(2);cola.imprimirCola();intv=cola.eliminar();System.out.println("Elemento eliminado "+v);cola.imprimirCola();}
Colas en C#
publicpartialclassfrmPrincipal{// Variables globalespublicstaticstring[]Cola;publicstaticintFrente;publicstaticintFinal;publicstaticintN;[STAThread]publicstaticvoidMain(string[]args){Application.EnableVisualStyles();Application.SetCompatibleTextRenderingDefault(false);Application.Run(newfrmPrincipal());}publicfrmPrincipal()// Constructor{InitializeComponent();Cola=newstring[5];// Arreglo lineal de 5N=4;Frente=-1;Final=-1;}voidCmdInsercionClick(objectsender,System.EventArgse){frmInsercionInsercion=newfrmInsercion();Insercion.Show();}voidCmdRecorridoClick(objectsender,System.EventArgse){frmRecorridoRecorrido=newfrmRecorrido();Recorrido.Show();}voidCmdBusquedaClick(objectsender,EventArgse){frmBusquedaBusqueda=newfrmBusqueda();Busqueda.Show();}voidCmdEliminacionClick(objectsender,EventArgse){frmEliminacionEliminar=newfrmEliminacion();Eliminar.Show();}}
Algoritmo Insertar(Cola, N, Frente, Final, Elemento)
voidCmdInsertarClick(objectsender,System.EventArgse){elemento=txtInsercion.Text;// Se verifica que haya espacio en la Colaif(frmPrincipal.Frente==0&&frmPrincipal.Final==frmPrincipal.N){MessageBox.Show("La Cola esta llena");return;}if(frmPrincipal.Frente==frmPrincipal.Final+1){MessageBox.Show("La Cola esta llena");return;}// Si la cola esta vacia se inicializan punterosif(frmPrincipal.Frente==-1){frmPrincipal.Frente=0;frmPrincipal.Final=0;}elseif(frmPrincipal.Final==frmPrincipal.N){frmPrincipal.Final=0;}else{frmPrincipal.Final=frmPrincipal.Final+1;}// Se agrega elemento a la ColafrmPrincipal.Cola[frmPrincipal.Final]=elemento;txtInsercion.Text="";}
Algoritmo Eliminación (Cola, Frente, Final, N)
voidCmdEliminarClick(objectsender,EventArgse){if(frmPrincipal.Frente==-1){MessageBox.Show("Cola Vacia");return;}stringelemento=frmPrincipal.Cola[frmPrincipal.Frente];// si la cola tiene un solo elementoif(frmPrincipal.Frente==frmPrincipal.Final){frmPrincipal.Frente=-1;frmPrincipal.Final=-1;}elseif(frmPrincipal.Frente==frmPrincipal.N){frmPrincipal.Frente=0;}else{frmPrincipal.Frente=frmPrincipal.Frente+1;}lsEliminado.Items.Add(elemento);}
Otra forma de programar una cola en Java
Por Jorge Herrera C
importjava.util.*;publicclassCola<Tipo>{privateList<Tipo>cola;publicCola(){cola=newArrayList<Tipo>();}publicbooleancolaVacia(){returncola.isEmpty();}publicvoidagregar(Tipoelemento){cola.add(elemento);}publicTiposacar(){if(colaVacia())returnnull;Tipoelemento=cola.get(0);cola.remove(0);returnelemento;}}// Fin de la clase Cola
A continuación un ejemplo de una clase manejadora de la clase Cola
publicclassManejador{publicstaticvoidmain(String[]args){Colacola=new<Integer>Cola();System.out.println(cola.sacar());cola.agregar(23);cola.agregar(24);cola.agregar(25);while(!cola.colaVacia()){System.out.println(cola.sacar());}Colanombres=new<String>Cola();nombres.agregar("Jorge");nombres.agregar("Raquel");nombres.agregar("Mayra Alejandra");while(!nombres.colaVacia()){System.out.println(nombres.sacar());}}}// Fin de la clase Manejadora
Colas de prioridad: En ellas, los elementos se atienden en el orden indicado por una prioridad asociada a cada uno. Si varios elementos tienen la misma prioridad, se atenderán de modo convencional según la posición que ocupen. Hay dos formas de implementación:
Añadir un campo a cada nodo con su prioridad. Resulta conveniente mantener la cola ordenada por orden de prioridad.
Crear tantas colas como prioridades haya, y almacenar cada elemento en su cola.
Bicolas (o Colas doblemente terminadas): son colas en donde los nodos se pueden añadir y quitar por ambos extremos; se les llama DEQUE (Double Ended QUEue). Para representar las bicolas lo podemos hacer con un array circular con Inicio y Fin que apunten a cada uno de los extremos. Hay variantes:
Bicolas de entrada restringida: Son aquellas donde la inserción solo se hace por el final, aunque podemos eliminar al inicio o al final.
Bicolas de salida restringida: Son aquellas donde solo se elimina por el final, aunque se puede insertar al inicio y al final.