两个栈实现一个队列
2013-09-07 22:12
393 查看
建了博客,可是一个字也没写过。今天写这个练手的简单小题目,看看会不会被砖头拍死。两个栈实现一个队列,不考虑效率的确不是什么难事。于是,我懒得做任何优化,只是尽量把代码写干净一点,用Java。接口和java.util.Queue类似(可能不是完全一样):offer方法表示入队,poll方法表示出队,peek方法是提取队头元素,empty方法检测队列是否为空。
思路很简单——我看了题目很快就能想出来思路的,想必是不难。想象两个栈A和B,一开始里面都没有元素。
入队(offer)时,只是在A中压入相应的元素。
出队(poll)时,由于需要的是A底部的元素,所以把A种的元素逐个弹出放入B中,就可以把顺序颠倒过来,使得A的底部元素成为B的顶部元素(ensureDequeue方法和exchangeStack方法)。
访问队列顶部元素(peek)和出队很接近,不用单独说了。
回到入队,如果B不是空的,那么需要和出队相反的操作(ensureEnqueue方法)。布尔变量mEnqueue用来区分当前是处于入队还是出队的状态,这样就可以决定要不要调用exchangeStack方法来”倾倒“某个栈。
我用了一堆assert来测试,只是因为我好久不用assert了。Java里直接写上assert是不够的,需要把你虚拟机的断言支持打开,网上一搜一堆,不再赘述。写完这段小程序,上网查了一下,发现可以优化的地方还是有的。比如:
mEnqueue这个状态变量可以拿掉,直接用两个栈是否为空来作为判断当前状态的条件。
exchangeStack方法中,不用把某一个栈完全倒空。比如,A中有若干元素,此时需要出队,那么出栈时A中的最后一个元素不用放到B中,直接拿出来就是要出队的元素。这样操作之后,两个栈的状态不会和上面给出的程序有任何不同,但是省了一次入栈操作。
如此等等。但是,我始终觉得这个问题充其量只能练练手,没有实用价值。当你入队N个元素,然后交替进行入队和出队操作,麻烦就来了。因为每一次操作,都需要对Θ(n)个元素做一次出栈和入栈操作,费力不讨好。
思路很简单——我看了题目很快就能想出来思路的,想必是不难。想象两个栈A和B,一开始里面都没有元素。
入队(offer)时,只是在A中压入相应的元素。
出队(poll)时,由于需要的是A底部的元素,所以把A种的元素逐个弹出放入B中,就可以把顺序颠倒过来,使得A的底部元素成为B的顶部元素(ensureDequeue方法和exchangeStack方法)。
访问队列顶部元素(peek)和出队很接近,不用单独说了。
回到入队,如果B不是空的,那么需要和出队相反的操作(ensureEnqueue方法)。布尔变量mEnqueue用来区分当前是处于入队还是出队的状态,这样就可以决定要不要调用exchangeStack方法来”倾倒“某个栈。
import java.util.Stack; class MyQueue<T> { private Stack<T> mStackEnqueue; private Stack<T> mStackDequeue; private boolean mEnqueue; public MyQueue() { mStackEnqueue = new Stack<T>(); mStackDequeue = new Stack<T>(); mEnqueue = true; } public void offer(T value) { ensureEnqueue(); mStackEnqueue.push(value); } public T poll() { ensureDequeue(); if (mStackDequeue.empty()) return null; return mStackDequeue.pop(); } public T peek() { ensureDequeue(); if (mStackDequeue.empty()) return null; return mStackDequeue.peek(); } public boolean empty() { if (mEnqueue) { return mStackEnqueue.empty(); } return mStackDequeue.empty(); } private void ensureEnqueue() { if (!mEnqueue) { exchangeStack(mStackDequeue, mStackEnqueue); mEnqueue = true; } } private void ensureDequeue() { if (mEnqueue) { exchangeStack(mStackEnqueue, mStackDequeue); mEnqueue = false; } } private void exchangeStack(Stack<T> src, Stack<T> dst) { assert dst.empty(); while (!src.empty()) { T tmp = src.pop(); dst.push(tmp); } } } public class Stack2Queue { public static void main(String[] args) { System.out.println("Start testing MyQueue"); MyQueue<Integer> myQueue = new MyQueue<Integer>(); assert myQueue.empty(); int length = 10; // enqueue for (int k = 0; k < length; ++k) { myQueue.offer(Integer.valueOf(k)); assert myQueue.peek().intValue() == 0; assert !myQueue.empty(); } // dequeue for (int k = 0; k < length; ++k) { assert myQueue.peek().intValue() == k; assert !myQueue.empty(); Integer kWrapped = myQueue.poll(); assert kWrapped.intValue() == k; } // dequeue when queue is empty assert myQueue.empty(); Integer nullInteger = myQueue.poll(); assert nullInteger == null; assert myQueue.empty(); // interleaved enqueue and dequeue for (int k = 0; k < length; ++k) { myQueue.offer(Integer.valueOf(k)); } for (int k = 0; k < length; ++k) { myQueue.offer(Integer.valueOf(k + length)); Integer kWrapped = myQueue.poll(); assert kWrapped.intValue() == k; } for (int k = 0; k < length; ++k) { Integer kWrapped = myQueue.poll(); assert kWrapped.intValue() == k + length; } System.out.println("Finish testing MyQueue"); } }
我用了一堆assert来测试,只是因为我好久不用assert了。Java里直接写上assert是不够的,需要把你虚拟机的断言支持打开,网上一搜一堆,不再赘述。写完这段小程序,上网查了一下,发现可以优化的地方还是有的。比如:
mEnqueue这个状态变量可以拿掉,直接用两个栈是否为空来作为判断当前状态的条件。
exchangeStack方法中,不用把某一个栈完全倒空。比如,A中有若干元素,此时需要出队,那么出栈时A中的最后一个元素不用放到B中,直接拿出来就是要出队的元素。这样操作之后,两个栈的状态不会和上面给出的程序有任何不同,但是省了一次入栈操作。
如此等等。但是,我始终觉得这个问题充其量只能练练手,没有实用价值。当你入队N个元素,然后交替进行入队和出队操作,麻烦就来了。因为每一次操作,都需要对Θ(n)个元素做一次出栈和入栈操作,费力不讨好。
相关文章推荐
- 两个栈实现一个队列的功能
- 用两个栈实现一个队列 & 用两个队列实现一个栈
- 用两个栈实现一个队列
- 使用两个栈实现一个队列+使用两个队列实现一个栈
- 两个栈实现一个队列-----两个队列实现一个栈
- 用两个队列实现一个栈
- [LeetCode-232] Implement Queue using Stacks(两个栈实现一个队列)
- 用来两个栈实现一个队列。
- 栈&队列面试题之两个队列实现一个栈
- 用两个栈实现一个队列和用两个队列实现一个栈
- 用两个栈实现一个队列
- 两个栈实现一个队列
- 用两个栈实现一个队列——我作为面试官的小结
- Java用两个队列实现一个栈的功能
- 两个栈实现一个队列&&两个队列实现一个栈
- 1.用两个栈实现队列 2.用两个队列实现一个栈
- 两个栈实现一个队列
- 用两个栈实现一个队列——我作为面试官的小结
- 用两个栈实现一个队列
- 两个栈实现一个队列