我们要用栈来实现队列,首先就是要清楚“栈”和“队列”的区别在哪?
“栈”(Stack):是一种先进后出(FILO:First In Last Out)的数据结构。
栈只能把元素一个一个压进去,取元素的时候只能从栈顶开始取,所以最晚入栈的元素,最早被取出来,最早入栈的元素就会最晚出栈。
“队列”(Queue):是先进先出(FIFO:First In First Out)的。
队列是从队尾添加元素,再从队头取出元素,最早入队的元素最早出队,最晚入队的元素最晚出队。
两者的方式时截然不同的,我们在搞清楚原理之后就开始思考,怎么去解决两者之间的问题。
思路:
我们可以创建两个栈,一个做为入队时用的栈(in),另一个做为出队时用的栈(out)。
private Stack<E> in = new Stack<E>(); // 入队栈
private Stack<E> out = new Stack<E>(); // 出队栈
在这里,我用泛型'E'来形容数据类型,确保在使用此方法时可以根据自己的需求选择元素类型。
我们在入队时,要确定所有的元素必须全都在“in”这个栈里,所以在进行入队操作时,要判断"out"栈是否为空,在确保"out"栈为空之后,我们才能开始入队操作。
// 入队
public void offer(E e) {
while(!out.isEmpty()) {
in.push(out.pop());
}
in.push(e);
}
反之,在出队时,也同样要确定所有的元素必须全都在“out”这个栈里,要对"in"栈进行判空,确保为空之后,开始出队操作。
// 出队
public E poll() {
while(!in.isEmpty()) {
out.push(in.pop());
}
return out.pop();
}
此外,我们在遍历队列时,要判断队列是否为空,就要对两个栈都进行判空做为循环结束的条件。
// 判断队列是否空
public boolean isEmpty() {
return in.size() == 0 && out.size() == 0;
}
完整代码展示:
import java.util.Stack;
public class Test01 {
public static void main(String[] args) {
MyQueue<String> queue = new MyQueue<String>();
queue.offer("A1");
queue.offer("A2");
queue.offer("A3");
queue.offer("A4");
System.out.println(queue.poll() + "出队");
queue.offer("A5"); // 入队新元素
// 遍历队列
while(!queue.isEmpty()) {
System.out.println(queue.poll());
}
}
}
// 栈模拟队列
class MyQueue<E>{
private Stack<E> in = new Stack<E>(); // 入队栈
private Stack<E> out = new Stack<E>(); // 出队栈
// 判断队列是否空
public boolean isEmpty() {
return in.size() == 0 && out.size() == 0;
}
// 入队
public void offer(E e) {
while(!out.isEmpty()) {
in.push(out.pop());
}
in.push(e);
}
// 出队
public E poll() {
while(!in.isEmpty()) {
out.push(in.pop());
}
return out.pop();
}
}