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
How to implement enqueue and dequeue using only two stacks in JavaScript?
In this tutorial, we'll implement a queue using only two stacks. This is a common data structure interview question that demonstrates understanding of both queues (FIFO - First In, First Out) and stacks (LIFO - Last In, First Out).
Algorithm
STEP 1 ? We have two stacks: one for enqueuing (input) and one for dequeuing (output).
STEP 2 ? We enqueue by pushing onto the enqueue stack.
STEP 3 ? We dequeue by popping from the dequeue stack.
STEP 4 ? If the dequeue stack is empty, we transfer all items from the enqueue stack to the dequeue stack.
STEP 5 ? This reverses the order so that the oldest item is now at the top of the dequeue stack.
Visual Representation
Implementation
Now let's see how this works in code. We'll create a Queue class with enqueue and dequeue methods:
class Queue {
constructor() {
this.enqueueStack = [];
this.dequeueStack = [];
}
enqueue(item) {
this.enqueueStack.push(item);
}
dequeue() {
if (this.dequeueStack.length === 0) {
// Move everything from enqueueStack to dequeueStack
while (this.enqueueStack.length > 0) {
const item = this.enqueueStack.pop();
this.dequeueStack.push(item);
}
}
// Dequeue from dequeueStack
return this.dequeueStack.pop();
}
isEmpty() {
return this.enqueueStack.length === 0 && this.dequeueStack.length === 0;
}
}
Example
Below is a complete working example demonstrating the queue operations:
<!DOCTYPE html>
<html>
<head>
<title>Queue using Two Stacks</title>
</head>
<body>
<h3>Implementing enqueue and dequeue using two stacks</h3>
<div id="result"></div>
<script>
class Queue {
constructor() {
this.enqueueStack = [];
this.dequeueStack = [];
}
enqueue(item) {
this.enqueueStack.push(item);
}
dequeue() {
if (this.dequeueStack.length === 0) {
while (this.enqueueStack.length > 0) {
const item = this.enqueueStack.pop();
this.dequeueStack.push(item);
}
}
return this.dequeueStack.pop();
}
isEmpty() {
return this.enqueueStack.length === 0 && this.dequeueStack.length === 0;
}
}
// Testing the queue
const queue = new Queue();
let output = "";
// Enqueue three items
queue.enqueue("First");
queue.enqueue("Second");
queue.enqueue("Third");
output += "Enqueued: First, Second, Third<br>";
// Dequeue items (should be in FIFO order)
output += "Dequeued: " + queue.dequeue() + "<br>"; // First
output += "Dequeued: " + queue.dequeue() + "<br>"; // Second
output += "Dequeued: " + queue.dequeue() + "<br>"; // Third
document.getElementById("result").innerHTML = output;
</script>
</body>
</html>
Enqueued: First, Second, Third Dequeued: First Dequeued: Second Dequeued: Third
Time Complexity
| Operation | Best Case | Worst Case | Amortized |
|---|---|---|---|
| Enqueue | O(1) | O(1) | O(1) |
| Dequeue | O(1) | O(n) | O(1) |
Pros and Cons
Advantages:
- Simple implementation using familiar stack operations
- Amortized O(1) time complexity for both operations
- Maintains FIFO order correctly
Disadvantages:
- Uses more memory than a single array implementation
- Worst-case O(n) time for dequeue when transfer is needed
- Less cache-friendly due to two separate data structures
Conclusion
Implementing a queue with two stacks is an elegant solution that maintains FIFO ordering through strategic use of stack reversal. While it has some overhead, the amortized performance makes it practical for interview scenarios and demonstrates deep understanding of data structure relationships.
