I have the following homework question:
Implement the stack methods push(x) and pop() using two queues.
This seems odd to me because:
- A Stack is a (LIFO) queue
- I don't see why you would need two queues to implement it
I searched around:
and found a couple solutions. This is what I ended up with:
public class Stack<T> {
LinkedList<T> q1 = new LinkedList<T>();
LinkedList<T> q2 = new LinkedList<T>();
public void push(T t) {
q1.addFirst(t);
}
public T pop() {
if (q1.isEmpty()) {
throw new RuntimeException(
"Can't pop from an empty stack!");
}
while(q1.size() > 1) {
q2.addFirst( q1.removeLast() );
}
T popped = q1.pop();
LinkedList<T> tempQ = q1;
q1 = q2;
q2 = tempQ;
return popped;
}
}
But I don't understand what the advantage is over using a single queue; the two queue version seems pointlessly complicated.
Say we choose for pushes to be the more efficient of the 2 (as I did above), push
would remain the same, and pop
would simply require iterating to the last element, and returning it. In both cases, the push
would be O(1)
, and the pop
would be O(n)
; but the single queue version would be drastically simpler. It should only require a single for loop.
Am I missing something? Any insight here would be appreciated.
Best Answer
There is no advantage: this is a purely academic exercise.
A very long time ago when I was a freshman in college I had a similar exercise1. The goal was to teach students how to use object-oriented programming to implement algorithms instead of writing iterative solutions using
for
loops with loop counters. Instead, combine and reuse existing data structures to achieve your goals.You will never use this code in the Real WorldTM. What you need to take away from this exercise is how to "think outside the box" and reuse code.
Please note that you should be using the java.util.Queue interface in your code instead of using the implementation directly:
This allows you to use other
Queue
implementations if desired, as well as hiding2 methods that are onLinkedList
that might get around the spirit of theQueue
interface. This includesget(int)
andpop()
(while your code compiles, there is a logic error in there given the constraints of your assignment. Declaring your variables asQueue
instead ofLinkedList
will reveal it). Related reading: Understanding “programming to an interface” and Why are interfaces useful?1 I still remember: the exercise was to reverse a Stack using only methods on the Stack interface and no utility methods in
java.util.Collections
or other "static only" utility classes. The correct solution involves using other data structures as temporary holding objects: you have to know the different data structures, their properties, and how to combine them to do it. Stumped most of my CS101 class who had never programmed before.2 The methods are still there, but you cannot access them without type casts or reflection. So it is not easy to use those non-queue methods.