Queues

A queue is a linear data structure that follows the First-In-First-Out (FIFO) principle. Like a line at a store, elements are added to the rear and removed from the front, ensuring fair processing order for tasks, scheduling, and breadth-first algorithms.

Interactive Queue Visualization

Experience the FIFO behavior of queues with animated enqueue and dequeue operations. Watch how elements enter from the right and exit from the left, with dynamic front and rear indicators.

Queue Operations (FIFO - First In, First Out)

Enqueue (Add to Rear)

Add to back of queue

Dequeue (Remove from Front)

Remove from front of queue

Front value: 10

Peek Front

Highlight front element

Peek Rear

Highlight rear element

Queue Visualization

queue[0]
10
queue[1]
20
queue[2]
30
FRONT
REAR

Queue Length: 3 / 8

Status: 3 elements in queue

Queue Contents: [front: 10 ← 20 ← 30 :rear]

How Queue Operations Work:

Enqueue (O(1)):

Add a new element to the rear (back) of the queue. New elements always join at the end of the line.

Dequeue (O(1)):

Remove and return the front element from the queue. Follows First-In-First-Out (FIFO) principle.

Peek Front/Rear (O(1)):

View the front or rear element without removing it. Useful for checking what's next to be processed.

FIFO Principle:

Queues follow the First-In-First-Out principle, meaning the first element added (enqueued) is the first one to be removed (dequeued). Think of a line at a store - the first person in line is the first person served.

Queue Characteristics

FIFO Principle

  • First In, First Out: Earliest added element is removed first
  • Two-End Access: Add at rear, remove from front
  • Fair Processing: Maintains order of arrival
  • Sequential Service: Elements processed in arrival order

Core Operations

  • Enqueue: Add element to the rear of the queue
  • Dequeue: Remove and return front element
  • Peek Front: View front element without removing
  • Peek Rear: View rear element without removing

Complexity Analysis

Operation Time Complexity Space Complexity Description
Enqueue O(1) O(1) Add element to rear in constant time
Dequeue O(1) O(1) Remove front element in constant time
Peek Front/Rear O(1) O(1) Access front/rear element without removal
Search O(n) O(1) Must dequeue elements to search (destructive)
Space - O(n) Linear space for n elements

Queue Implementation with Applications

Complete queue implementations with practical applications like task scheduling (Java) and BFS traversal (Python). Study how the FIFO principle ensures fair processing in real-world scenarios.

# Queue implementation using Python collections.deque
from collections import deque

class Queue:
    """
    A First-In-First-Out (FIFO) data structure implementation
    Using Python deque for efficient operations at both ends
    """
    def __init__(self):
        self.items = deque()
    
    def enqueue(self, item):
        """
        Add an item to the rear of the queue
        Like a person joining the back of a line
        
        Time Complexity: O(1)
        Space Complexity: O(1)
        """
        self.items.append(item)
        print(f"Enqueued {item}. Queue: {list(self.items)}")
    
    def dequeue(self):
        """
        Remove and return the front item from the queue
        Like the first person in line being served
        
        Time Complexity: O(1)
        Space Complexity: O(1)
        
        Raises:
            IndexError: If queue is empty
        """
        if self.is_empty():
            raise IndexError("dequeue from empty queue")
        
        item = self.items.popleft()
        print(f"Dequeued {item}. Queue: {list(self.items)}")
        return item
    
    def peek_front(self):
        """
        Return the front item without removing it
        Like looking at who's first in line
        
        Time Complexity: O(1)
        Space Complexity: O(1)
        
        Raises:
            IndexError: If queue is empty
        """
        if self.is_empty():
            raise IndexError("peek at empty queue")
        
        return self.items[0]
    
    def peek_rear(self):
        """
        Return the rear item without removing it
        Like looking at who's last in line
        
        Time Complexity: O(1)
        Space Complexity: O(1)
        """
        if self.is_empty():
            raise IndexError("peek at empty queue")
        
        return self.items[-1]
    
    def is_empty(self):
        """Check if the queue is empty"""
        return len(self.items) == 0
    
    def size(self):
        """Return the number of items in the queue"""
        return len(self.items)
    
    def display(self):
        """Display queue contents from front to rear"""
        if self.is_empty():
            return "Empty Queue"
        return f"Queue (front → rear): {list(self.items)}"

# Example usage demonstrating FIFO principle
def demonstrate_fifo():
    """Demonstrate how queue follows FIFO principle"""
    queue = Queue()
    
    print("=== Demonstrating FIFO Principle ===")
    print("Think of this like a line at a store...")
    
    # Enqueue items (people joining the line)
    print("\nPeople joining the line:")
    queue.enqueue("Alice (first)")
    queue.enqueue("Bob (second)")  
    queue.enqueue("Charlie (third)")
    
    print(f"\nFront person: {queue.peek_front()}")
    print(f"Rear person: {queue.peek_rear()}")
    print(f"Queue size: {queue.size()}")
    
    # Dequeue items (people being served)
    print("\nServing people (FIFO order):")
    while not queue.is_empty():
        person = queue.dequeue()
        print(f"Served: {person}")
    
    print(f"\nQueue is now empty: {queue.is_empty()}")

# Breadth-First Search simulation using queue
def bfs_simulation():
    """Simulate BFS traversal using a queue"""
    print("\n=== BFS Simulation ===")
    print("Traversing a tree level by level using queue")
    
    # Tree representation: each node has children
    tree = {
        'A': ['B', 'C'],
        'B': ['D', 'E'], 
        'C': ['F'],
        'D': [],
        'E': ['G'],
        'F': [],
        'G': []
    }
    
    queue = Queue()
    visited = []
    
    # Start with root node
    queue.enqueue('A')
    
    print("\nBFS Traversal:")
    while not queue.is_empty():
        current = queue.dequeue()
        visited.append(current)
        print(f"Visiting: {current}")
        
        # Add children to queue
        for child in tree[current]:
            if child not in visited:
                queue.enqueue(child)
                print(f"  Added {child} to queue")
    
    print(f"\nTraversal order: {' → '.join(visited)}")

if __name__ == "__main__":
    # Basic queue operations
    demonstrate_fifo()
    
    # Practical application
    bfs_simulation()

Real-World Applications

Task Scheduling

Operating systems use queues to schedule processes and manage CPU time allocation fairly.

Breadth-First Search

Graph algorithms use queues to explore nodes level by level in BFS traversal.

Print Queue

Printer spoolers use queues to process print jobs in the order they were submitted.

Web Server Requests

Web servers queue incoming requests to handle them fairly and prevent overwhelming the system.

Buffer for Data Streams

Queues buffer data between producers and consumers at different processing speeds.

Call Center Systems

Phone systems queue incoming calls to ensure callers are helped in the order they called.