Day 17: Stack & Queue

Welcome to Day 17 of the Python Interview Challenge! Today, we're diving into two fundamental data structures: Stacks and Queues. Understanding these is crucial for a wide range of programming problems and is a common topic in technical interviews.

1. Introduction to Stack & Queue

Both Stacks and Queues are linear data structures, meaning they store data in a sequential manner. The key difference lies in how elements are added and removed.

Real-world examples:

2. Explanation of Stack

A Stack is an abstract data type that serves as a collection of elements, with two primary operations: push and pop.

The LIFO principle is central to its operation. The last element added is the first one to be removed.

3. Explanation of Queue

A Queue is a linear data structure that operates based on the FIFO principle. Elements are added to the back and removed from the front.

4. Python Implementations

Using a List as a Stack

Python's built-in list can be easily used to implement a stack. The append() method acts as push, and pop() acts as pop.


# Stack implementation using a list
stack = []

# Push elements
stack.append('A') # push()
stack.append('B') # push()
stack.append('C') # push()
print("Stack after pushes:", stack)

# Peek at the top element
if stack:
    print("Top element (peek):", stack[-1])

# Pop elements
popped_item = stack.pop() # pop()
print("Popped item:", popped_item)
print("Stack after pop:", stack)

# Check if empty
print("Is stack empty?", not stack)
        

Using collections.deque as a Queue

While a list can technically be a queue (using append() and pop(0)), pop(0) is inefficient for large lists. The collections.deque (double-ended queue) is highly optimized for this purpose and is the preferred way to implement a queue in Python.


from collections import deque

# Queue implementation using deque
queue = deque()

# Enqueue elements
queue.append('A') # enqueue()
queue.append('B') # enqueue()
queue.append('C') # enqueue()
print("Queue after enqueues:", queue)

# Dequeue elements
dequeued_item = queue.popleft() # dequeue()
print("Dequeued item:", dequeued_item)
print("Queue after dequeue:", queue)

# Front of the queue
if queue:
    print("Front element:", queue[0])
        

Using the queue Module

The built-in queue module is designed for multithreaded programming, but its Queue class is also a great way to implement a standard queue.


from queue import Queue

# Queue implementation using the queue module
q = Queue()

# Enqueue elements
q.put('A') # enqueue()
q.put('B') # enqueue()
q.put('C') # enqueue()
print("Queue size:", q.qsize())

# Dequeue elements
dequeued_item = q.get() # dequeue()
print("Dequeued item:", dequeued_item)
print("Queue size after dequeue:", q.qsize())
        

5. Advantages & Disadvantages

6. Common Interview Questions with Answers

Here are some conceptual questions you might encounter:

  1. What is the difference between a stack and a queue?
    The main difference is the order of element access. A stack is LIFO (Last-In, First-Out), while a queue is FIFO (First-In, First-Out).
  2. When would you use a stack over a queue?
    Use a stack for problems where the last item to be added is the first one you need to process. Examples include function call stacks, undo/redo functionality, and expression parsing.
  3. What is a real-world example of a queue?
    A printer queue is a classic example. Jobs are added to the queue and printed in the order they were submitted. Other examples include waiting lines and task scheduling in an operating system.

7. Summary & Key Points