两个队列实现一个栈
入栈
入队队列 1 即可。
出栈
- 如果队列 1 和队列 2 同时为空说明此栈为空,不应该调用出栈方法,这里给他抛出个异常即可。
- 如果队列 1 不为空,队列 2 为空,说明此时需要将队列 1 除开队尾元素以外元素迁移到队列 2 中(入队方式迁移),此时出队队列 1 的队尾即可。
- 如果队列 1 为空,队列 2 不为空,说明我们已经将数据迁移至队列 2 中,此时我们只需要将数据 2 的数据先迁移回队列 1 然后再进行第二种情况的操作即可。
注意:这里有小伙伴可能会疑问为什么没有考虑队列 1,2 都不会为空,发生这种情况是在调用过一次出栈方法后会导致队列 1 的数据迁移到队列 2 此时如果我们调用入栈方法元素会入队队列 1 中。
我们不考虑这种情况是因为我们可以通过优先判断队列 1 完成,不需要附加额外代码。
因为我们这里是模拟两个队列实现栈,栈的特点就是后进先出,上述情况中后序入栈的元素存放在队列 1 中,此时队列 1 的 size 从 0 -> 1,如果我们下个操作是出栈则直接将队列 1 唯一元素出队即可,如果后序操作是再入栈几个元素再出栈的话,那么因为我们是先执行判断队列 1 的操作,所以我们会继续将除开队尾元素入队队列 2,然后再出队队列 1(换句话说就是队列只有在size = 1时才会出队,如果 > 1时只会将除了队尾元素出队到队列 2 中,直到size = 1再次尝试出队)
import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;
public class TwoQueue {
private Stack<String> stack = new Stack<>();
//作为队列 1 率先存放
Queue<String> queue1 = new LinkedList<>();
//作为一个临时保存数据的队列
Queue<String> queue2 = new LinkedList<>();
//入栈
private void push(String s) {
queue1.offer(s);
}
//出栈
public String pop() {
if(queue1.isEmpty() && queue2.isEmpty()) {
throw new NullPointerException("栈空");
}
if(!queue1.isEmpty()) { //说明队列 1 中存在元素
if(queue1.size() != 1) {
while(queue1.size() > 1) {
//将队列 1 留下队尾元素,剩余元素入队到队列 2
queue2.offer(queue1.poll());
}
}
return queue1.poll();
} else { //栈中无数据或者队列 1 出列完毕
while(!queue2.isEmpty()) {
//将队列 2 中数据入队队列 1 (相当于是一个数据迁移)
queue1.offer(queue2.poll());
}
//重新调用该方法,因为需要再次进行数据迁移(类似递归但是他最多会调用一次,所以不用担心栈内存溢出问题)
return pop();
}
}
public static void main(String[] args) {
TwoQueue twoQueue = new TwoQueue();
twoQueue.push("1");
twoQueue.push("2");
twoQueue.push("3");
System.out.println(twoQueue.pop());
System.out.println(twoQueue.pop());
System.out.println(twoQueue.pop());
twoQueue.push("4");
}
}