两个堆栈实现队列
分析
堆栈是先进后出,队列是先进先出,用两个堆栈倒腾两次正好把顺序反过来就能实现队列的操作。
一个堆栈用来出队(可以叫stackPop),一个堆栈用来入队(可以叫stackPush)。
要实现先进先出,要把数据从stachPush中倒腾到stackPop中,倒腾的时候,必须保证两点:
(1). stackPush往stackPop倒腾的时候,必须一次把stackPush的时候全部弹出去。
(2).stackPop中有数据的时候,不能倒腾。
入队很简单,直接push到stackPop中。 出队时stackPop里没有元素的话,就把stackPush里面的元素都倒腾过来,然后出去一个就好了。出队时如果stackPop里有元素,就直接出去一个就ok。代码
public class StackIntoQueue {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
if(stack2.empty()){
while(!stack1.empty()){
stack2.push(stack1.pop());
}
}
int ans = stack2.pop();
return ans;
}
}
两个队列实现堆栈
- 分析
用一个变量来表示目前正在操作的队列。入栈时就把元素加入该队列。出栈时,把该队列中的元素(除了最后一个)都转移到另一个队列中,最后出栈最后这个元素,并把那个变量指示为含有元素的那个队列。
(Java中其实LinkedList就封装了堆栈和队列(包括双端队列)的所有操作,LinkedList底层是一个就是一个双向链表。所以下面的代码有些牵强,就仅仅是用LinkedList中队列的操作来模拟栈的操作) - 代码
package niuke;
import java.util.*;
public class QueueIntoStack {
private LinkedList<Integer> queue1 = new LinkedList<Integer>();
private LinkedList<Integer> queue2 = new LinkedList<Integer>();
private int pushTmp = 1;
void push(int x){
if(pushTmp == 1){
queue1.addLast(x);
}else {
queue2.addLast(x);
}
}
int pop(){
int ans = 0, size = 0;
if(pushTmp == 1){
size = queue1.size();
for(int i=0; i<size-1; i++){
queue2.addLast(queue1.removeFirst());
}
pushTmp = 2; //修改pushTmp的值
ans = queue1.removeFirst();
}else {
size = queue2.size();
for(int i=0; i<size-1; i++){
queue1.addLast(queue2.removeFirst());
}
pushTmp = 1;
ans = queue2.removeFirst();
}
return ans;
}
public static void main(String[] args) {
QueueIntoStack stack = new QueueIntoStack();
for(int i = 0; i<10; i++)
stack.push(i);
for(int i = 0; i<10; i++)
System.out.println(stack.pop());
}
}
两个堆栈实现队列(加入容量条件)
- 题目链接
堆栈模拟队列 - 问题描述:
如何用两个堆栈模拟实现一个队列? 如果这两个堆栈的容量分别是m和n(m>n),你的方法能保证的队列容量是多少? 分析
上面第一题是不考虑堆栈的容量,如果有了容量限制,我们首先要确定要哪个堆栈的容量大(m),哪的堆栈的容量小(n)。根据第一题的分析:stackPush往stackPop倒腾的时候,必须一次把stackPush的时候全部弹出去。
即stackPop中必须能够容纳stackPush中的所有数据,那么很容易就想到stackPop堆栈的容量大(为m),stackPush堆栈的容量小(为n),能保证的堆栈容量就是 n*2。我的代码
class StackToQueue{
private Stack<Integer> stackPush;
private Stack<Integer> stackPop;
private int pushSize,popSize;
public StackToQueue(int n1, int n2){
stackPush = new Stack<>();
stackPop = new Stack<>();
this.pushSize = Math.min(n1, n2);
this.popSize = Math.max(n1, n2);
}
public boolean isEmpty(){
return stackPop.empty() && stackPush.empty();
}
public void push(int data){
if (stackPush.size() == pushSize){
if (!stackPop.empty()){
System.out.println("ERROR:Full");
return;
} else {
while (!stackPush.empty()){
stackPop.push(stackPush.pop());
}
}
}
stackPush.push(data);
}
public int pop(){
if (stackPop.empty() && stackPush.empty()){
System.out.println("ERROR:Empty");
throw new EmptyStackException();
}
if (stackPop.empty()){
while (!stackPush.empty()){
stackPop.push(stackPush.pop());
}
}
return stackPop.pop();
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int N1,N2;
N1 = in.nextInt();
N2 = in.nextInt();
StackToQueue queue = new StackToQueue(N1, N2);
while (in.hasNext()){
String op = in.next();
int data;
switch (op.trim()){
case "A":
data = in.nextInt();
queue.push(data);
break;
case "D":
try {
data = queue.pop();
System.out.println(data);
} catch (EmptyStackException e){
}
break;
case "T": System.exit(0);
}
}
}
}