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:
Table of Contents
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:
- Push: Add an element to the top of the stack.
- Pop: Remove and return the element from the top of the stack.
- Peek/Top: Return the top element without removing it.
- isEmpty: Check if the stack is empty.
- 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:
- Function Call Management: Used in programming languages for keeping track of function calls (call stack).
- Undo/Redo: In text editors or graphics software.
- Expression Evaluation: For evaluating and converting expressions (e.g., infix to postfix).
- Parenthesis Matching: To check balanced parentheses in an expression.
- 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:
- Enqueue: Add an element to the rear (end) of the queue.
- Dequeue: Remove and return the element from the front of the queue.
- Peek/Front: Return the front element without removing it.
- isEmpty: Check if the queue is empty.
- 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:
- Push Operation (O(1)):
- Add the element to Queue1.
- 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:
- 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.
- 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)
[…] How to implement stack using queue […]