Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Selected Reading
Python Program to Implement Queues using Stacks
When it is required to implement a queue using stacks, we can create a queue class that uses two stack instances. This approach leverages the LIFO (Last In First Out) nature of stacks to achieve FIFO (First In First Out) behavior of queues.
A queue has two main operations: enqueue (add element) and dequeue (remove element). We'll use two stacks − one for input operations and another for output operations.
How It Works
The algorithm uses two stacks:
- Input Stack: Handles all enqueue operations
- Output Stack: Handles all dequeue operations
- When dequeuing, if output stack is empty, transfer all elements from input stack to output stack
Implementation
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return len(self.items) == 0
def push(self, data):
self.items.append(data)
def pop(self):
if not self.is_empty():
return self.items.pop()
return None
class QueueUsingStacks:
def __init__(self):
self.input_stack = Stack()
self.output_stack = Stack()
def is_empty(self):
return self.input_stack.is_empty() and self.output_stack.is_empty()
def enqueue(self, data):
self.input_stack.push(data)
print(f"Enqueued: {data}")
def dequeue(self):
if self.output_stack.is_empty():
while not self.input_stack.is_empty():
element = self.input_stack.pop()
self.output_stack.push(element)
if not self.output_stack.is_empty():
return self.output_stack.pop()
return None
# Example usage
queue = QueueUsingStacks()
# Enqueue elements
queue.enqueue(10)
queue.enqueue(20)
queue.enqueue(30)
# Dequeue elements
print(f"Dequeued: {queue.dequeue()}")
print(f"Dequeued: {queue.dequeue()}")
# Enqueue more elements
queue.enqueue(40)
print(f"Dequeued: {queue.dequeue()}")
print(f"Dequeued: {queue.dequeue()}")
print(f"Queue is empty: {queue.is_empty()}")
Enqueued: 10 Enqueued: 20 Enqueued: 30 Dequeued: 10 Dequeued: 20 Enqueued: 40 Dequeued: 30 Dequeued: 40 Queue is empty: True
Interactive Queue Implementation
class Stack:
def __init__(self):
self.items = []
def is_empty(self):
return len(self.items) == 0
def push(self, data):
self.items.append(data)
def pop(self):
if not self.is_empty():
return self.items.pop()
return None
class QueueUsingStacks:
def __init__(self):
self.input_stack = Stack()
self.output_stack = Stack()
def is_empty(self):
return self.input_stack.is_empty() and self.output_stack.is_empty()
def enqueue(self, data):
self.input_stack.push(data)
def dequeue(self):
if self.output_stack.is_empty():
while not self.input_stack.is_empty():
element = self.input_stack.pop()
self.output_stack.push(element)
if not self.output_stack.is_empty():
return self.output_stack.pop()
return None
# Interactive menu
my_queue = QueueUsingStacks()
while True:
print('\nOptions:')
print('1. enqueue <value>')
print('2. dequeue')
print('3. quit')
user_input = input('What operation would you like to perform? ').split()
if len(user_input) == 0:
continue
operation = user_input[0].strip().lower()
if operation == 'enqueue' and len(user_input) > 1:
try:
value = int(user_input[1])
my_queue.enqueue(value)
print(f'Enqueued: {value}')
except ValueError:
print('Please enter a valid number')
elif operation == 'dequeue':
if my_queue.is_empty():
print('The queue is empty')
else:
deleted_element = my_queue.dequeue()
print(f'Dequeued: {deleted_element}')
elif operation == 'quit':
break
else:
print('Invalid operation')
Time Complexity
| Operation | Average Case | Worst Case |
|---|---|---|
| Enqueue | O(1) | O(1) |
| Dequeue | O(1) | O(n) |
Key Points
- Enqueue operation is always O(1) as we simply push to input stack
- Dequeue operation is amortized O(1) but can be O(n) in worst case
- Each element is moved at most twice (once to output stack, once out of it)
- Space complexity is O(n) where n is the number of elements
Conclusion
Implementing a queue using two stacks provides an efficient way to achieve FIFO behavior. The enqueue operation is always O(1), while dequeue has an amortized time complexity of O(1), making this approach practical for most applications.
Advertisements
