题目描述
【题目】:
编写一个类,用两个栈实现队列,满足队列的基本操作要求:enqueue(入队)、出队(dequeue),peek:获取队列中对头元素。
【解答】
- 栈数据结构的特点是先进后出,而队列数据结构的特点是先进先出。用两个栈正好能把顺序反过来实现类似队列的操作。
- 具体实现上是一个栈作为压入数据栈,在压入数据栈时,只往这个栈中压入数据(入队),记为 stackPush,另一个栈只作为弹出栈,在弹出数据(出队)只从这个栈弹出,记为 stackPop。
- 因为数据压入栈的时候,顺序时先进后出的。那么只要把 stackPush 的数据再压入 stackPop 中,顺序就变回来了。
【举个栗子】
把 1~5 依次压入 stackPush ,那么从stackPush 的栈顶的栈底为 5~1 ,此时再将 5~1 倒stackPop,那么从 stackPop 的栈顶到栈底就变成了 1~5.再从 stackPop 弹出时,顺序就像队列一样,如图所示:
听起来貌似简单,但实际上必须做到以下两点:
1.如果 stackPush 要往 stackPop 中压入数据,那么必须一次性把 stackPush 中的数据全部压入。
2.如果 stackPop 不为空,stackPush 绝对不能向 stackPop 中压入数据。
违反了以上两点,都会发生错误。
- 违反 1 的情况举例:1~5 依次次压入stackPush,stackPush 的栈顶到栈底为 5~1,从 stackPush 压入 stackPop 时,如果只将 5 和 4 压入了 stackPop ,stackPush 还剩下 1、2、3 没有压入。此时如果用户想进行出队操作,那么 4 将最先弹出,与预想的队列顺序就不一致。
- 违反 2 的情况举例:1~5 依次压入 stackPush,将 stackPush 中的所有数据压入了 stackPop ,此时从 stackPop 栈顶到栈底为 1~5。此时,又有 6~10 压入 stackPop ,这时候stackPop 不为空不能压入数据,如果违反2,向 stackPop 压入数据,stackPop 栈顶到栈底为 6~10,1~5,此时用户如果想进行出队操作,那么 6 将最先弹出,又与预想的队列顺序不一致。
代码实现
上述介绍了压入数据的注意事项。具体实现参看如下代码:
1public class TwoStackQueue {
2 private Stack<Integer> stackPush;
3 private Stack<Integer> stackPop;
4
5 public TwoStackQueue() {
6 stackPush = new Stack<Integer>();
7 stackPop = new Stack<Integer>();
8 }
9
10 //TODO:入队操作,往队列中添加数据
11 public void enqueue(int newData) {
12 this.stackPush.push(newData);
13 }
14
15 //TODO:出队操作,从队列中获取数据,注意队列数据结构是先进先出
16 public int dequeue() {
17 if (stackPush.empty() && stackPop.empty()) {
18 throw new RuntimeException("Queue is empty!");
19 } else if (stackPop.empty()) {
20 while (!stackPush.empty()) {
21 this.stackPop.push(this.stackPush.pop());
22 }
23 }
24 return stackPop.pop();
25 }
26
27 //TODO:获取队列中的队头元素
28 public int peek() {
29 if (stackPush.empty() && stackPop.empty()) {
30 throw new RuntimeException("Queue is empty!");
31 }else if (stackPop.empty()) {
32 while (!stackPush.empty()) {
33 this.stackPop.push(this.stackPush.pop());
34 }
35 }
36 return stackPop.peek();
37 }
38}
本段代码是在在调用 dequeue 和 peek 方法时进行压入数据的过程。这个压入数据的操作选择的时机可以有很多,调用 enqueue、dequeue 和 peek 三种方法中的任何一种时发生压入数据的行为都是可以的。只要不违反上述两点,就不会出错。