Queue (cola)
Última actualización
Una cola tiene dos extremos activos. Los valores nuevos entran por el final y los valores salen por el frente, así que el que lleva más tiempo esperando es el primero al que se atiende. Eso es FIFO, y es exactamente como se comporta una fila en un mostrador: entrar por detrás y ser atendido por delante es lo que hace justa la espera. Pulsa reproducir arriba y observa cómo los valores entran por un lado y salen por el otro.
Como cada extremo se controla con su propio índice o puntero, las dos operaciones son O(1) y ninguna desplaza el resto de los datos. Por eso las colas están debajo de todo lo que procesa trabajo por orden de llegada: trabajos de impresión, colas de tareas y de mensajes, búferes de peticiones y la búsqueda en anchura, que recorre un grafo nivel a nivel precisamente porque guarda su frontera en una cola. Mueve al final el extremo por el que quitas y lo que tienes es un Stack (pila).
Complejidad temporal y espacial
Para una cola respaldada por un búfer circular o por una lista enlazada, las dos implementaciones estándar:
| Operación | Complejidad | Notas |
|---|---|---|
| Encolar | O(1) | Escribe en el final y avanza el índice del final. |
| Desencolar | O(1) | Lee en el frente y avanza el índice del frente, sin desplazar nada. |
| Peek (frente) | O(1) | Lee el valor del frente sin quitarlo. |
| Buscar | O(n) | No es para lo que sirve una cola: tienes que vaciarla para mirar dentro. |
| Espacio | O(n) | Un hueco por cada valor en espera. |
Paso a paso
| Paso | Qué ocurre |
|---|---|
| 1 | La cola empieza vacía, con el frente y el final apuntando al mismo hueco. |
| 2 | Encolar escribe el valor en el final y luego avanza el final una posición. |
| 3 | Cada encolado posterior cae detrás de los valores que ya están esperando. |
| 4 | Desencolar lee el valor del frente y luego avanza el frente una posición. |
| 5 | El valor que devuelve es siempre el que lleva más tiempo esperando. |
| 6 | Cuando el frente alcanza al final la cola vuelve a estar vacía, y seguir desencolando es un error. |
Ejemplo resuelto
Encolando 3, 7, 5 y luego vaciando la cola:
| Operación | Cola (del frente al final) | Devuelve |
|---|---|---|
enqueue(3) | [3] | nada |
enqueue(7) | [3, 7] | nada |
enqueue(5) | [3, 7, 5] | nada |
dequeue() | [7, 5] | 3, el valor más antiguo |
dequeue() | [5] | 7 |
dequeue() | [] | 5, el valor más nuevo, el último |
Cuándo usar una cola
| Úsala cuando | Evítala cuando |
|---|---|
| El trabajo debe atenderse por orden de llegada: colas de tareas, búferes de peticiones, gestores de impresión | Necesitas primero el elemento más reciente, que es un Stack (pila) |
| Estás explorando nivel a nivel, como hace la búsqueda en anchura | Los elementos deben atenderse por prioridad y no por llegada, donde encaja un heap |
| Un productor y un consumidor van a velocidades distintas y necesitan un búfer entre ambos | Necesitas buscar o indexar en medio de los datos |
Quieres inserción y eliminación O(1) sin desplazar elementos | La implementarías desplazando un arreglo en cada desencolado, lo que la vuelve O(n) |
Código de Queue
Una implementación limpia y ejecutable de Queue en Python, JavaScript, Java, C++, C. Elige un lenguaje, copia el código o ábrelo ya cargado en el Playground de Coddy.
Código de Queue en Python
1from collections import deque2
3queue = deque()4
5# Enqueue three values at the rear6for value in [3, 7, 5]:7 queue.append(value)8 print(f"enqueue {value} -> {list(queue)}")9
10# Dequeue them from the front: first in, first out11while queue:12 value = queue.popleft()13 print(f"dequeue {value} -> {list(queue)}")14
15print("empty:", len(queue) == 0)Código de Queue en JavaScript
1// A plain array makes dequeue O(n): shift() moves every element left.2// Track a head index instead, the fix the queue article describes.3const queue = { items: [], head: 0 };4
5function enqueue(value) {6 queue.items.push(value);7}8
9function dequeue() {10 const value = queue.items[queue.head];11 queue.items[queue.head] = undefined; // free the slot12 queue.head += 1;13 // Reclaim space once the consumed prefix dominates.14 if (queue.head * 2 >= queue.items.length) {15 queue.items = queue.items.slice(queue.head);16 queue.head = 0;17 }18 return value;19}20
21const size = () => queue.items.length - queue.head;22
23for (const value of [3, 7, 5]) {24 enqueue(value);25 console.log(`enqueue ${value} -> size ${size()}`);26}27
28// Dequeue from the front: first in, first out, amortized O(1)29while (size() > 0) {30 console.log(`dequeue ${dequeue()} -> size ${size()}`);31}32
33console.log('empty:', size() === 0);Código de Queue en Java
1import java.util.ArrayDeque;2import java.util.Queue;3
4public class Main {5 public static void main(String[] args) {6 Queue<Integer> queue = new ArrayDeque<>();7
8 // Enqueue three values at the rear9 for (int value : new int[] {3, 7, 5}) {10 queue.add(value);11 System.out.println("enqueue " + value + " -> " + queue);12 }13
14 // Dequeue them from the front: first in, first out15 while (!queue.isEmpty()) {16 int value = queue.remove();17 System.out.println("dequeue " + value + " -> " + queue);18 }19
20 System.out.println("empty: " + queue.isEmpty());21 }22}Código de Queue en C++
1#include <iostream>2#include <queue>3
4int main() {5 std::queue<int> queue;6
7 // Enqueue three values at the rear8 for (int value : {3, 7, 5}) {9 queue.push(value);10 std::cout << "enqueue " << value << " -> size " << queue.size() << "\n";11 }12
13 // Dequeue them from the front: first in, first out14 while (!queue.empty()) {15 int value = queue.front();16 queue.pop();17 std::cout << "dequeue " << value << " -> size " << queue.size() << "\n";18 }19
20 std::cout << "empty: " << std::boolalpha << queue.empty() << "\n";21 return 0;22}Código de Queue en C
1#include <stdio.h>2
3#define CAP 164
5int queue[CAP];6int front = 0;7int rear = 0; /* index of the next free slot */8
9int main(void) {10 int values[3] = {3, 7, 5};11
12 /* Enqueue three values at the rear */13 for (int i = 0; i < 3; i++) {14 queue[rear++] = values[i];15 printf("enqueue %d -> size %d\n", values[i], rear - front);16 }17
18 /* Dequeue them from the front: first in, first out */19 while (front < rear) {20 int value = queue[front++];21 printf("dequeue %d -> size %d\n", value, rear - front);22 }23
24 printf("empty: %d\n", front == rear);25 return 0;26}Preguntas frecuentes sobre las colas
¿Qué significa FIFO?
¿Cuál es la diferencia entre una cola y una pila?
O(1); una cola quita por el frente (FIFO) y una pila quita por el mismo extremo por el que añadió (LIFO). Por lo demás, sus tablas de complejidad son idénticas.¿Cuáles son las operaciones principales de una cola?
enqueue añade un valor al final, dequeue quita y devuelve el valor del frente, peek (o front) lee el frente sin quitarlo, y is_empty indica si queda algo esperando. Las cuatro son O(1).¿Por qué desencolar es lento si uso un arreglo normal?
O(n). Las implementaciones reales lo evitan con un búfer circular que avanza un índice de frente, o con una lista enlazada con un puntero a la cabeza. collections.deque de Python y ArrayDeque de Java lo hacen por ti, mientras que list.pop(0) no.¿Qué es una cola circular?
n sigue funcionando indefinidamente en vez de salirse del final del arreglo.