Implementing a queue using two stacks is a common interview question that demonstrates understanding of stack operations and how they can be used to simulate a queue. Here's how you can implement a queue using two stacks in Python:
class QueueUsingStacks:
def __init__(self):
self.stack1 = []
self.stack2 = []
def enqueue(self, item):
# Push item into stack1
self.stack1.append(item)
def dequeue(self):
if not self.stack2:
# Transfer all elements from stack1 to stack2
while self.stack1:
self.stack2.append(self.stack1.pop())
# Pop from stack2 if it's not empty
if self.stack2:
return self.stack2.pop()
else:
raise IndexError("dequeue from empty queue")
def peek(self):
if not self.stack2:
# Transfer all elements from stack1 to stack2
while self.stack1:
self.stack2.append(self.stack1.pop())
# Peek from stack2 if it's not empty
if self.stack2:
return self.stack2[-1]
else:
return None
def is_empty(self):
return not self.stack1 and not self.stack2
def size(self):
return len(self.stack1) + len(self.stack2)
Explanation:
Initialization (
__init__method):- Initializes two empty lists
self.stack1andself.stack2.self.stack1will be used for enqueue operations, andself.stack2will be used for dequeue operations.
- Initializes two empty lists
Enqueue operation (
enqueuemethod):- Adds an item to the end of
self.stack1using theappendmethod.
- Adds an item to the end of
Dequeue operation (
dequeuemethod):- Checks if
self.stack2is empty. - If
self.stack2is empty, transfers all elements fromself.stack1toself.stack2by popping fromself.stack1and pushing ontoself.stack2. - Finally, pops and returns the top element from
self.stack2.
- Checks if
Peek operation (
peekmethod):- Similar to
dequeue, checks ifself.stack2is empty and transfers elements fromself.stack1toself.stack2if needed. - Returns the top element of
self.stack2without removing it.
- Similar to
is_empty method:
- Checks if both
self.stack1andself.stack2are empty and returnsTrueif they are,Falseotherwise.
- Checks if both
size method:
- Returns the total number of elements in the queue, which is the sum of the lengths of
self.stack1andself.stack2.
- Returns the total number of elements in the queue, which is the sum of the lengths of
Example Usage:
enqueue operation simply appends elements to self.stack1. The dequeue and peek operations first check if self.stack2 is empty; if it is, they transfer elements from self.stack1 to self.stack2 to ensure FIFO (first-in-first-out) order is maintained. This approach ensures that enqueueing and dequeueing operations are efficient, each operating in amortized time complexity.
