栈和队列理论基础
- 栈 :先进后出
- 队列 :先进先出
Java中队列Queue的操作
- 队列
使用Queue接口创建队列 ,Queue的实现类有LinkedList和ArrayDeque。最常用的实现类是LinkedList。
Queue的六种方法:
- add()和 offer()
向队列中添加元素,将元素压入队尾。当超出容量时add()会抛出异常 , offer()会返回false。 - remove() 和 poll()
移除元素,将元素从队头移出。当当前容量为0执行移除操作时,remove()会抛出异常 , poll()会返回false。 - element() 和 peek()
获取队头元素,当前容量为0时。element()会抛出异常 , peek()会返回null。
- 栈
使用Stack类创建栈,Stack是Java中本身具有的集合类型,所包含的方法包括:
- boolean isEmpty() // 判断当前栈是否为空
- synchronized E peek() //获得当前栈顶元素
- synchronized E pop() //获得当前栈顶元素并删除
- push(E object) //将元素加入栈顶
- synchronized int search(Object o) //查找元素在栈中的位置,由栈低向栈顶方向数
232.用栈实现队列
leetcode链接
思路: 用两个栈实现队列。
注意: 可以看出peek()的实现,直接复用了pop(), 要不然,对stOut判空的逻辑又要重写一遍。
再多说一些代码开发上的习惯问题,在工业级别代码开发中,最忌讳的就是 实现一个类似的函数,直接把代码粘过来改一改就完事了。
这样的项目代码会越来越乱,一定要懂得复用,功能相近的函数要抽象出来,不要大量的复制粘贴,很容易出问题!(踩过坑的人自然懂)
class MyQueue {
Stack<Integer> stackIn;
Stack<Integer> stackOut;
public MyQueue() {
stackIn=new Stack<>();
stackOut=new Stack<>();
}
public void push(int x) {
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();
}
// 如果stackOut为空,那么将stackIn中的元素全部放到stackOut中
private void dumpstackIn(){
if(!stackOut.isEmpty()){
return;
}else{
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();
*/
时间复杂度: pop为O(n),其他为O(1)
空间复杂度: O(n)
225. 用队列实现栈
leetcode链接
思路: 用一个queue就可以实现栈
- 每次添加元素直接再队列末尾追加
- 删除元素时需要依次把除末尾元素之外的元素删除并重新移到队列末尾,使要删除的元素位于队列的队首。
- 获取最顶端元素时,如果是LinkedList实现的队列,需要执行依次移位后获取当前队首元素(即原队列的队尾元素)后,删除当前队首元素,并重新添加到队尾。如果是ArrayDeque实现的话,则可以直接使用que1.peekLast()获取队尾元素。
方法一 LinkedList实现
追加元素 queue.add(x)/.offer(x);
弹出元素 queue.poll(x)/remove(x);
获取队首元素 queue.peek()/element();
class MyStack {
Queue<Integer> queue;
public MyStack() {
queue=new LinkedList<>();
}
public void push(int x) {
queue.add(x);
}
public int pop() {
rePosition();
return queue.poll();
}
public int top() {
rePosition();
int result=queue.poll();
queue.add(result);
return result;
}
public boolean empty() {
return queue.isEmpty();
}
public void rePosition(){
int size=queue.size();
for(int i=0;i<(size-1);i++){
queue.add(queue.poll());
}
}
}
/**
* Your MyStack object will be instantiated and called as such:
* MyStack obj = new MyStack();
* obj.push(x);
* int param_2 = obj.pop();
* int param_3 = obj.top();
* boolean param_4 = obj.empty();
*/
**方法二 ArrayDeque实现
队尾追加元素 queue.addLast(x);
队首弹出元素 queue.pollFirst();
获取队首元素 queue.peekFirst();
获取队尾元素 queue.peekLast();
class MyStack {
// Deque 接口继承了 Queue 接口
// 所以 Queue 中的 add、poll、peek等效于 Deque 中的 addLast、pollFirst、peekFirst
Deque<Integer> que1;
/** Initialize your data structure here. */
public MyStack() {
que1 = new ArrayDeque<>();
}
/** Push element x onto stack. */
public void push(int x) {
que1.addLast(x);
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
int size = que1.size();
size--;
// 将 que1 导入 que2 ,但留下最后一个值
while (size-- > 0) {
que1.addLast(que1.peekFirst());
que1.pollFirst();
}
int res = que1.pollFirst();
return res;
}
/** Get the top element. */
public int top() {
return que1.peekLast();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return que1.isEmpty();
}
}
时间复杂度: pop为O(n),其他为O(1)
空间复杂度: O(n)