HomeCore ConceptsHow to implement Stack using queue

How to implement Stack using queue

- Advertisement -spot_img

To implement a stack using queue, you can use two queues. The basic idea is to reverse the order of elements so that the last element inserted into the stack becomes the first element dequeued (mimicking the stack’s Last-In-First-Out, LIFO, behaviour). Here’s how you can implement it using two queues:

What is stack in Data Structure

A stack is a linear data structure that follows the Last In, First Out (LIFO) principle. This means the last element added to the stack will be the first one to be removed. Think of it as a stack of plates: you add plates on top and remove them from the top.

Key Operations:

  1. Push: Add an element to the top of the stack.
  2. Pop: Remove and return the element from the top of the stack.
  3. Peek/Top: Return the top element without removing it.
  4. isEmpty: Check if the stack is empty.
  5. Size: Return the number of elements in the stack.

Characteristics:

  • Operations happen only at one end (the top of the stack).
  • Does not allow random access; elements are accessed in LIFO order.

Applications:

  1. Function Call Management: Used in programming languages for keeping track of function calls (call stack).
  2. Undo/Redo: In text editors or graphics software.
  3. Expression Evaluation: For evaluating and converting expressions (e.g., infix to postfix).
  4. Parenthesis Matching: To check balanced parentheses in an expression.
  5. Navigation: In web browsers (forward and backward navigation).

What is Queue in Data Structure

A queue is a linear data structure that follows the First In, First Out (FIFO) principle. This means the first element added to the queue will be the first one to be removed. It is analogous to a line of people waiting for a service, where the person who arrives first gets served first.


Key Operations:

  1. Enqueue: Add an element to the rear (end) of the queue.
  2. Dequeue: Remove and return the element from the front of the queue.
  3. Peek/Front: Return the front element without removing it.
  4. isEmpty: Check if the queue is empty.
  5. Size: Return the number of elements in the queue.

Characteristics:

  • Operations are performed at two ends:
    • Front: For removing elements.
    • Rear: For adding elements.

How to implement stack using queue

A stack can be implemented using one or two queues by simulating the Last In, First Out (LIFO) behavior using First In, First Out (FIFO) queues.

Approach 1: Using Two Queues (Efficient Push Operation) Stack using queue

In this approach, the push operation is efficient, but the pop operation takes more time.

Steps:

  1. Push Operation (O(1)):
    • Add the element to Queue1.
  2. Pop Operation (O(n)):
    • Remove elements from Queue1 one by one and enqueue them into Queue2 until only one element remains in Queue1.
    • This remaining element is the “top” of the stack (last inserted).
    • Dequeue the last element from Queue1 (which is the “top” of the stack).
    • Swap Queue1 and Queue2 to prepare for the next operation.

Python Implementation:

from queue import Queue

class StackUsingQueues:
    def __init__(self):
        # Create two queues
        self.queue1 = Queue()
        self.queue2 = Queue()

    def push(self, data):
        # Push data to queue1
        self.queue1.put(data)

    def pop(self):
        if self.queue1.empty():
            return None  # Stack is empty

        # Move all elements from queue1 to queue2 except the last one
        while self.queue1.qsize() > 1:
            self.queue2.put(self.queue1.get())

        # The last element in queue1 is the top of the stack
        popped_element = self.queue1.get()

        # Swap the queues
        self.queue1, self.queue2 = self.queue2, self.queue1

        return popped_element

    def top(self):
        if self.queue1.empty():
            return None  # Stack is empty

        # Move all elements from queue1 to queue2 except the last one
        while self.queue1.qsize() > 1:
            self.queue2.put(self.queue1.get())

        # The last element in queue1 is the top of the stack
        top_element = self.queue1.get()

        # Put it back in queue1
        self.queue2.put(top_element)

        # Swap the queues
        self.queue1, self.queue2 = self.queue2, self.queue1

        return top_element

    def is_empty(self):
        return self.queue1.empty()

# Example usage:
stack = StackUsingQueues()
stack.push(10)
stack.push(20)
stack.push(30)

print(stack.pop())  # 30
print(stack.top())  # 20
print(stack.pop())  # 20
print(stack.is_empty())  # False
print(stack.pop())  # 10
print(stack.is_empty())  # True

Approach 2: Using Two Queues (Efficient Pop Operation) – stack using queue

Alternatively, you can make the pop operation efficient by modifying the implementation slightly.

Steps:

  1. Push Operation (O(n)):
    • Add the element to Queue1.
    • Move all elements from Queue2 to Queue1 before adding the new element, so the new element is always at the front of Queue1.
  2. Pop Operation (O(1)):
    • Simply dequeue the element from Queue1.

This way, the pop operation is O(1), but the push operation is O(n) because you need to transfer all the elements from one queue to the other.

Python Implementation:

from queue import Queue

class StackUsingQueues:
    def __init__(self):
        # Create two queues
        self.queue1 = Queue()
        self.queue2 = Queue()

    def push(self, data):
        # Move all elements from queue1 to queue2
        while not self.queue1.empty():
            self.queue2.put(self.queue1.get())
        
        # Add the new element to queue1
        self.queue1.put(data)
        
        # Move all elements back to queue1
        while not self.queue2.empty():
            self.queue1.put(self.queue2.get())

    def pop(self):
        if self.queue1.empty():
            return None  # Stack is empty
        return self.queue1.get()

    def top(self):
        if self.queue1.empty():
            return None  # Stack is empty
        top_element = self.queue1.get()
        self.queue2.put(top_element)  # Put it back into queue2 for future pops
        self.queue1.put(top_element)  # Put it back into queue1 for top consistency
        return top_element

    def is_empty(self):
        return self.queue1.empty()

# Example usage:
stack = StackUsingQueues()
stack.push(10)
stack.push(20)
stack.push(30)

print(stack.pop())  # 30
print(stack.top())  # 20
print(stack.pop())  # 20
print(stack.is_empty())  # False
print(stack.pop())  # 10
print(stack.is_empty())  # True

Comparison:

  • Approach 1 (Efficient Push, O(1) for push, O(n) for pop): This is useful when you expect more push operations than pop operations.
  • Approach 2 (Efficient Pop, O(n) for push, O(1) for pop): This is useful when you expect more pop operations than push operations.

Both approaches for stack using queue in Data Structure demonstrate how you can simulate stack behavior using queues, with trade-offs depending on the pattern of operations

.Unlocking the Power of Python in Natural Language Processing (NLP)

Stay Connected
16,985FansLike
2,458FollowersFollow
61,453SubscribersSubscribe
Must Read
Related News

1 COMMENT

LEAVE A REPLY

Please enter your comment!
Please enter your name here