5. Queues
🧸 ELI5: A queue is the line at an ice cream truck. Whoever got in line first gets their ice cream first. No cutting! You join at the back, you leave from the front. First one in, first one out (FIFO).
🌍 Real life: A printer queue (the first document you sent prints first). People waiting for a rollercoaster. Customer support tickets.
📝 Pseudocode:
queue = []
enqueue(queue, "Alice")
enqueue(queue, "Bob")
dequeue(queue) // removes "Alice" (the first one who joined)
🐹 Go:
package main
import "fmt"
type Queue struct {
items []string
}
func (q *Queue) Enqueue(item string) {
q.items = append(q.items, item)
}
func (q *Queue) Dequeue() (string, bool) {
if len(q.items) == 0 {
return "", false
}
first := q.items[0]
q.items = q.items[1:]
return first, true
}
func main() {
iceCreamLine := &Queue{}
iceCreamLine.Enqueue("Alice")
iceCreamLine.Enqueue("Bob")
served, _ := iceCreamLine.Dequeue()
fmt.Println("served:", served) // served: Alice
}
🇨 C (a circular buffer — head/tail indices wrap around with %, so unlike Go's slice trick, nothing ever gets shifted in memory):
#include <stdio.h>
#include <string.h>
#define QUEUE_CAP 32
typedef struct {
char items[QUEUE_CAP][64];
int head, tail, count;
} Queue;
void queue_enqueue(Queue *q, const char *item) {
if (q->count >= QUEUE_CAP) return;
strncpy(q->items[q->tail], item, sizeof q->items[0] - 1);
q->tail = (q->tail + 1) % QUEUE_CAP;
q->count++;
}
int queue_dequeue(Queue *q, char *out, size_t out_cap) {
if (q->count == 0) return 0;
strncpy(out, q->items[q->head], out_cap - 1);
q->head = (q->head + 1) % QUEUE_CAP;
q->count--;
return 1;
}
int main(void) {
Queue iceCreamLine = {0};
queue_enqueue(&iceCreamLine, "Alice");
queue_enqueue(&iceCreamLine, "Bob");
char served[64];
if (queue_dequeue(&iceCreamLine, served, sizeof served)) {
printf("served: %s\n", served); // served: Alice
}
return 0;
}
⏱️ Complexity: Enqueue/Dequeue = O(1) (with a proper ring buffer/linked list; Go's slice trick above is O(1) amortized but not perfectly optimal).