A stack can be implemented using two queues. Here’s how you can implement the push and pop operations of a stack:
1. Push operation: For every pushed element, we remove all elements from ‘queue1‘ and append them to ‘queue2‘, then add the pushed element in ‘queue1‘ and finally add back all elements from ‘queue2‘ to ‘queue1‘. So, after any push operation, ‘queue1‘ will always contain the full stack so that its head is the top of the stack.
Here’s a Python implementation of the ‘push‘ operation:
def push(x):
# Pushing x to queue1
queue1.append(x)
# Pushing the rest of the elements in queue1 into queue2
for _ in range(len(queue1)-1):
queue1.append(queue1.pop(0))
2. Pop operation: As we maintained the condition where the head of ‘queue1‘ is always the top of the stack, ‘pop()‘ operation is as simple as dequeuing from ‘queue1‘.
Here’s the Python implementation of the ‘pop‘ operation:
def pop():
# if first queue is empty
if len(queue1) == 0:
print("Stack is Empty.")
return
return queue1.pop(0)
Here’s a visual representation of the process:
For instance, suppose we're pushing 1, 2, and 3 in this order:
Initially: queue1=[]
Push 1: queue1=[1]
Push 2: queue2=[1], queu1=[2], queue1=[2,1]
Push 3: queue2=[2,1], queue1=[3], queue1=[3,2,1]
So in this case, to get the top of the stack (3), we just return the front of queue1. To pop, we simply dequeue from queue1.
You must note that this method makes the ‘push‘ operation more costly. The ‘push‘ operation takes O(n) time as it involves reversing ‘queue1‘ with helping of ‘queue2‘. Meanwhile, the ‘pop‘ operation only takes O(1) time. If you want to make the ‘push‘ operation less costly, you might want to reverse the roles of ‘queue1‘ and ‘queue2‘ in the ‘push‘ and ‘pop‘ operations.
Also note that the above implementation is not thread safe. If multiple threads execute operations on the stack at the same time, the behavior might violate the Stack data structure’s contract.