Queue Basics

A queue is a linear data structure that follows the First-In-First-Out (FIFO) principle. Think of it like a line at a store - the first person in line is the first to be served.

Core Operations

  • Enqueue: Add an element to the back of the queue - O(1)
  • Dequeue: Remove and return the front element - O(1)
  • Peek/Front: View the front element without removing it - O(1)
  • isEmpty: Check if the queue is empty - O(1)

When to Use Queues

Queues are ideal when you need to:

  • Process items in order of arrival
  • Implement breadth-first search (BFS)
  • Handle tasks in a scheduling system
  • Buffer data streams
  • Implement caching systems (FIFO eviction)

Implementation with Array

class Queue {
  constructor() {
    this.items = [];
  }

  enqueue(element) {
    this.items.push(element);
  }

  dequeue() {
    if (this.isEmpty()) return null;
    return this.items.shift(); // O(n) - not ideal!
  }

  front() {
    if (this.isEmpty()) return null;
    return this.items[0];
  }

  isEmpty() {
    return this.items.length === 0;
  }

  size() {
    return this.items.length;
  }
}

Better Implementation with Two Pointers

class Queue:
    def __init__(self):
        self.items = []
        self.front_index = 0

    def enqueue(self, item):
        self.items.append(item)

    def dequeue(self):
        if self.is_empty():
            return None

        item = self.items[self.front_index]
        self.front_index += 1

        # Reset when queue is empty
        if self.front_index == len(self.items):
            self.items = []
            self.front_index = 0

        return item

    def front(self):
        if self.is_empty():
            return None
        return self.items[self.front_index]

    def is_empty(self):
        return self.front_index >= len(self.items)

    def size(self):
        return len(self.items) - self.front_index

Using Python's deque

Python's collections.deque is optimized for queue operations:

from collections import deque

queue = deque()
queue.append(1)      # Enqueue
queue.append(2)
item = queue.popleft()  # Dequeue - O(1)
front = queue[0]     # Peek

JavaScript Queue Pattern

// Using array methods (not optimal)
const queue = [];
queue.push(1); // Enqueue
const item = queue.shift(); // Dequeue

// Better: Use two arrays
class OptimizedQueue {
  constructor() {
    this.inbox = [];
    this.outbox = [];
  }

  enqueue(item) {
    this.inbox.push(item);
  }

  dequeue() {
    if (this.outbox.length === 0) {
      while (this.inbox.length > 0) {
        this.outbox.push(this.inbox.pop());
      }
    }
    return this.outbox.pop();
  }
}

Key Insight

Queues preserve order - the first item enqueued is the first item dequeued. This makes them perfect for problems requiring level-by-level or breadth-first processing.