← Back to Course

Template

Stacks and Queues: Core Concepts

Stacks and Queues

Core Concepts for Coding Interviews

Section 1: Core Concept (Clubbed)

Introduction

Stacks and queues are fundamental linear data structures commonly tested in coding interviews. Each enforces a different access order: a stack uses Last-In-First-Out (LIFO) ordering, while a queue uses First-In-First-Out (FIFO). In practice this means a stack always removes the most recently added element first, whereas a queue always removes the longest-waiting element first.

Interview problems often leverage these behaviors – for example, a stack might be used for backtracking or expression parsing, while a queue suits level-by-level traversal or task scheduling.

When to use a Stack vs. Queue?

  • Stack (LIFO): Use for “recently used” or “undo” scenarios, nested/recursive structures (e.g., parentheses matching), or backtracking.
  • Queue (FIFO): Use for “first-come, first-served” processing, level-order traversal (BFS), or buffering incoming data in order.

Core Idea / Mental Model

Stack (Last-In, First-Out): Imagine a stack of plates. You push new items onto the top, and pop items off from the top. The last item added is the first removed. Like an "undo" operation or programming call stack.

Queue (First-In, First-Out): Think of a line of people. The first person in line is served first; new people join at the end. You enqueue (add) at the back (rear) and dequeue (remove) from the front. Ensures fairness, used in BFS or task schedulers.

Base Template (Python)

Basic algorithmic patterns using a stack and a queue:

Stack-based Depth-First Search (DFS) template

# Assume start_node and node.neighbors are defined
stack = [start_node]
visited = {start_node}
while stack:
    node = stack.pop() # LIFO
    # process(node)
    for neighbor in reversed(node.neighbors): # Process left children first if applicable
        if neighbor not in visited:
            stack.append(neighbor)
            visited.add(neighbor)

In DFS, new elements go on top of the stack, processed before older ones. visited set prevents cycles in graphs.

Queue-based Breadth-First Search (BFS) template

from collections import deque
# Assume start_node and node.neighbors are defined
queue = deque([start_node])
visited = {start_node}
while queue:
    node = queue.popleft() # FIFO
    # process(node)
    for neighbor in node.neighbors:
        if neighbor not in visited:
            queue.append(neighbor)
            visited.add(neighbor)

In BFS, elements are processed in arrival order. deque ensures O(1) enqueue/dequeue. visited set prevents cycles.

Animation (Stack vs. Queue Operations)

The animation below demonstrates the fundamental LIFO (Stack) and FIFO (Queue) behaviors. Select a mode, enter a number, and use Push/Pop or Enqueue/Dequeue to see how the structure changes.

Stack Example (DFS-like on A -> (B,C), B -> (D,E)):
  1. Start: stack = [A].
  2. Pop A. Push C, then B. Stack: [C, B] (top B). Processed: A.
  3. Pop B. Push E, then D. Stack: [C, E, D] (top D). Processed: A, B.
  4. Pop D. Stack: [C, E] (top E). Processed: A, B, D.
  5. Pop E. Stack: [C] (top C). Processed: A, B, D, E.
  6. Pop C. Stack: []. Processed: A, B, D, E, C.
Queue Example (BFS-like on same tree):
  1. Start: queue = [A].
  2. Dequeue A. Enqueue B, C. Queue: [B, C] (front B). Processed: A.
  3. Dequeue B. Enqueue D, E. Queue: [C, D, E] (front C). Processed: A, B.
  4. Dequeue C. Queue: [D, E] (front D). Processed: A, B, C.
  5. Dequeue D. Queue: [E] (front E). Processed: A, B, C, D.
  6. Dequeue E. Queue: []. Processed: A, B, C, D, E.
Stack is empty

Select mode, enter value, and operate.

Time & Space Complexity

Operations Complexity:

OperationStack (LIFO)Queue (FIFO)
Push (insert)O(1)
Pop (remove)O(1)
Enqueue (insert)O(1)
Dequeue (remove)O(1)
Peek/FrontO(1)O(1)

These complexities assume efficient implementations (e.g., Python's list for stack, collections.deque for queue).

Algorithmic Complexity:

Many algorithms using stacks/queues (like BFS/DFS on n nodes) run in O(n) time. Space complexity is also often O(n) for storing elements or visited sets. For graphs, BFS/DFS are O(V+E) time and space.

Note: Using Python list's pop(0) for dequeuing is O(n). Prefer collections.deque for O(1) queue operations.

Common Pitfalls

  • Off-by-one Errors: Miscalculating boundaries with array-based implementations.
  • Forgetting Empty Checks: Popping/dequeuing from empty structures causes errors.
  • Infinite Loops: Not updating loop conditions or visited sets correctly in traversals.
  • Wrong Base/Edge Conditions: Missing base cases in recursion or improper loop setup.
  • Incorrect Order of Operations: Pushing/enqueuing in an order that yields wrong processing sequence (e.g., for DFS stack, push neighbors in reverse of desired visit order).
  • Neglecting to Free or Reset: Carrying over stale data if reusing structures across test cases.
  • Using Suboptimal Operations: E.g., Python list's pop(0) for queue dequeue (O(n)) instead of deque.popleft() (O(1)).

© Stacks and Queues Core Concepts. Content adapted for educational purposes.

We use cookies to improve your experience. By clicking “Accept” you consent to the use of cookies. Read our Privacy Policy.