Stack & Queue Visualizer

Interactive visualization of Stack (LIFO) and Queue (FIFO) data structures. Watch push, pop, enqueue, and dequeue operations in action.

📚 Stack (LIFO)

Last In, First Out

40← TOP
30
20
10

🚶 Queue (FIFO)

First In, First Out

FRONT →
10
20
30
40
← REAR

Stack vs Queue Comparison

FeatureStackQueue
PrincipleLIFO (Last In First Out)FIFO (First In First Out)
Add OperationPush (top)Enqueue (rear)
Remove OperationPop (top)Dequeue (front)
Time ComplexityO(1) all opsO(1) all ops
Use CasesUndo, recursion, parsingBFS, task scheduling, buffers

Understanding Stacks and Queues

Stacks and queues are two of the most fundamental data structures in computer science. Despite their simplicity—each supports only a handful of operations—they appear everywhere in computing: from the call stack that manages function execution to the message queues that coordinate distributed systems. Understanding when and how to use each is essential knowledge for every programmer.

Both structures are abstract data types defined by their behavior rather than their implementation. A stack enforces Last-In-First-Out (LIFO) order: the most recently added element is removed first, like a stack of plates. A queue enforces First-In-First-Out (FIFO) order: elements are removed in the order they were added, like a line of people waiting.

Stack: The LIFO Structure

A stack supports three primary operations: push adds an element to the top, pop removes and returns the top element, and peek (or top) returns the top element without removing it. All operations execute in O(1) constant time because they only affect one end of the structure.

The most pervasive use of stacks is the call stack that manages program execution. When a function is called, a stack frame containing parameters, local variables, and the return address is pushed onto the call stack. When the function returns, its frame is popped. This is why recursive functions that recurse too deeply cause "stack overflow" errors—the call stack runs out of space.

Stacks also power the undo functionality in applications. Each action pushes a record onto the undo stack. When you press Ctrl+Z, the last action is popped and reversed. A separate redo stack holds undone actions. Text editors, graphics programs, and countless other applications use this pattern.

Queue: The FIFO Structure

A queue supports enqueue (add to the rear), dequeue (remove from the front), and front (peek at the front element). Like stacks, all operations are O(1). The implementation is slightly more complex because operations happen at both ends.

Queues model any first-come-first-served scenario: customers waiting for service, print jobs waiting for a printer, or tasks waiting for CPU time. The operating system scheduler uses queues to manage process execution fairly. Message queues like RabbitMQ and Apache Kafka use queue semantics to coordinate communication between distributed services.

Breadth-First Search (BFS) algorithms use queues to explore graphs level by level. Starting node goes in the queue; then repeatedly dequeue a node, process it, and enqueue its unvisited neighbors. This ensures nodes are visited in order of their distance from the start.

Implementation Approaches

Both structures can be implemented using arrays or linked lists. Array implementation is cache-friendly and simple but may require resizing. For stacks, you maintain a pointer to the top; push increments it and pop decrements it. For queues, you maintain front and rear pointers, typically using a circular buffer to avoid wasted space.

Linked list implementation avoids resizing overhead and uses exactly the memory needed. For stacks, push and pop both operate on the head of the list. For queues, enqueue at the tail and dequeue from the head, requiring pointers to both ends for O(1) operations.

JavaScript arrays have push/pop (stack) and push/shift (queue) methods built in. However, shift() is O(n) because it requires moving all elements. For performance-critical queue operations, consider a dedicated queue implementation with circular buffer or linked list.

Variations and Extensions

Deque (double-ended queue) supports insertion and removal at both ends. It can function as either a stack or a queue, offering flexibility at the cost of a slightly more complex interface.

Priority Queue removes elements in priority order rather than insertion order. The highest-priority (or lowest, depending on convention) element is always removed first. Typically implemented with a heap, priority queues enable efficient algorithms like Dijkstra's shortest path.

Circular Queue wraps around when it reaches the end of its array, reusing space at the beginning. This avoids the problem of a queue appearing full when space exists at the front after dequeue operations.

Real-World Applications

Browser history: The back button uses a stack. Each page visit pushes onto the stack; back pops the current page and shows the previous. The forward button uses a second stack for returned pages.

Expression evaluation: Compilers use stacks to parse and evaluate expressions. The shunting-yard algorithm converts infix notation (3 + 4 * 2) to postfix (3 4 2 * +) using a stack, and another stack evaluates the postfix expression.

Buffer management: Keyboard input, network packets, and audio streams all use queues to buffer data between producers and consumers operating at different speeds. The producer enqueues; the consumer dequeues when ready.

Task scheduling: Operating systems use queues (often priority queues) to schedule processes. Web servers queue incoming requests when handlers are busy. Background job systems like Sidekiq and Celery process jobs from queues.

Choosing Stack vs Queue

The choice depends on the order in which elements should be processed. If the most recent item is most relevant (like returning from a function or undoing an action), use a stack. If fairness matters and items should be processed in the order received, use a queue.

Depth-First Search uses a stack (often the implicit call stack through recursion). Breadth-First Search uses a queue. This single difference fundamentally changes the order of exploration and the algorithm's behavior.

When processing needs to balance recency and fairness, consider hybrid approaches. A time-limited stack might process recent items first but fall back to older items if they wait too long. Priority queues can balance multiple factors in determining processing order.