栈和队列
栈的理论基础
栈概念:栈是一种特殊的线性表,只允许在一端进行插入和删除元素操作
栈顶:进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。在操作一个栈的时候,只能操作这个栈的栈顶
栈原则:先进后出
队列的理论基础
队列的概念:队列只允许在一端进行插入数据操作,在另一端进行删除数据的特殊线性表
队列原则:先进先出
入队列:进行插入操作的一端称为队尾(tail)
出队列:进行删除操作的一端称为队头(head)
元素的出队顺序和入队顺序保持一致
232.用栈实现队列
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):
实现 MyQueue 类:
void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false
输入:
["MyQueue", "push", "push", "peek", "pop", "empty"] [[], [1], [2], [], [], []]
输出:
[null, null, null, 1, 1, false]
解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false
思路
1.用栈实现队列首先要知道栈的原则:先进后出 队列原则:先进先出
举例:在栈里边放123,出栈应该是321 在队列里边放123,出队列应该是123
用栈实现队列就是想让栈里边先出1 2 3,那要借助另一个栈,我们称为出栈,把进栈的元素挪到出栈里边,然后在对出栈做一系列的操作就可以实现用栈实现队列了。
代码
class MyQueue {
Stack<Integer> stackIn;//定义一个入栈
Stack<Integer> stackOut;//定义一个出栈
public MyQueue() {
stackIn=new Stack<>();//负责进栈
stackOut=new Stack<>();//负责出栈
}
public void push(int x) {
//把元素都放到stackIn里面
stackIn.push(x);
}
public int pop() {
dumpStackIn();
return stackOut.pop();
}
public int peek() {
dumpStackIn();
return stackOut.peek();
}
public boolean empty() {
return stackIn.isEmpty()&&stackOut.isEmpty();
}
public void dumpStackIn(){//把stackIn里边的元素都移到stackOut里面
if(!stackOut.isEmpty()){return;}//如果出栈为空,那要把入栈里面所有元素都放到出栈里
while(!stackIn.isEmpty()){
stackOut.push(stackIn.pop());
}
}
}
/**
* Your MyQueue object will be instantiated and called as such:
* MyQueue obj = new MyQueue();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.peek();
* boolean param_4 = obj.empty();
*/
复杂度分析
1.入队stackIn.push
时间复杂度O(1):直接把元素推进stackIn里面
空间复杂度O(1)
2.出队stackOut.pop()
时间复杂度O(N),需要把所有元素全部压入stackOut栈中,再出栈一个元素;
空间复杂度O(N)需要额外的N个内存来储存队列中的元素;
3.取队首元素.peek()
因为需要把元素全都压入stackOut,然后再peek,时间复杂度O(N);
空间复杂度O(N);
判断空stack.isEmpty()
只需要判断两个栈是否为空即可,时间复杂度O(1),空间复杂度O(1)