Implement Stack using Queue Data Structure

Stacks are a fundamental data structure that follow the Last-In-First-Out (LIFO) principle. This principle is exactly opposite of First-In-First-Out (FIFO) principle on Queue data structure is based on. While stacks can be implemented directly using an array or a linked list, they can also be constructed using two queues.

Implementing a stack with queues involves maintaining two queues, where one queue is used to store the elements, while the other queue is used to reverse the order of the elements when popping from the stack. Below is a basic program which demonstrates implementing a stack data structure using two queue objects:


from queue import Queue

class Stack:
  def __init__(self):
    self.q1 = Queue()
    self.q2 = Queue()

  def push(self, item):
    """
    Adds an item to the top of the stack.
    * First add the current item to Queue q2
    * Next add all the items present in Queue q1 to q2
    * Now Swap q1 and q2
    * Now q1 contains recently added item at the beginning
    * and oldest added element at the ending
    * So when get is called on queue, recently added element
    * will be returned, similar to Stack ADT
    """
    self.q2.put(item)
    while not self.q1.empty():
      self.q2.put(self.q1.get())
    self.q1, self.q2 = self.q2, self.q1

  def pop(self):
    """
    Removes and returns the top item from the stack.
    """
    if self.q1.empty():
      raise IndexError("Stack is empty")
    return self.q1.get()

  def peek(self):
    """
    Returns the top item from the stack without removing it.
    """
    if self.q1.empty():
      raise IndexError("Stack is empty")
    return self.q1.queue[0]

  def is_empty(self):
    """
    Returns True if the stack is empty, False otherwise.
    """
    return self.q1.empty()

# Let's now test the Stack implementation
stack = Stack()
stack.push(1)
stack.push(2)
stack.push(3)
print("Popping last element: ", stack.pop())  # Output: 3
print("Peeking last element: ", stack.peek())  # Output: 2
print("Popping last element: ", stack.pop())  # Output: 2
print(stack.is_empty())  # Output: False, since item 1 is still in stack

Here’s how the implementation works:

  1. The Stack class has two queue objects, q1 and q2, which are used to implement the stack.
  2. The push() method adds an item to the top of the stack. It does this by first adding the item to q2, and then moving all the items from q1 to q2. Finally, it swaps the references to q1 and q2 so that q1 now contains the updated stack.
  3. The pop() method removes and returns the top item from the stack. It does this by checking if q1 is empty, and if so, raising an error. Otherwise, it returns the item at the front of q1.
  4. The peek() method returns the top item from the stack without removing it. It does this by checking if q1 is empty, and if so, raising an error. Otherwise, it returns the item at the front of q1.
  5. The is_empty() method returns True if the stack is empty, and False otherwise.