一、队列和栈
1、栈和队列的性质
- 栈是先进后出
- 队列是先进先出
栈和队列在实现结构上可以有数组和链表两种形式:其中数组结构实现较容易,用链表结构较复杂,因为牵扯很多指针操作。
2、栈结构的基本操作
(1)pop操作:从栈顶弹出一个元素
(2)top和peek操作:访问栈顶元素,但是不弹出
(3)push操作:从栈顶压入一个元素
(4)size操作:返回栈中的元素个数
3、队列结构的基本操作
和栈不同的是
(1)push操作:在队列的队头加入元素
(2)pop操作:从队列尾部弹出一个元素
栈和队列的基本操作,都是时间复杂度为O(1)的操作
双端队列:首尾都可以压入和弹出元素
优先级队列:根据元素的优先级值,决定元素的弹出顺序,优先级队列的结构实际上不是线性结构,而是堆结构。
4、与栈和队列相关的图的遍历
深度优先遍历(DFS)和宽度有限遍历(BFS)
深度遍历可以用栈实现,宽度优先遍历可以用队列实现。
二、可查询最值的栈
题型:
实现一个特殊的栈,在实现栈的基本功能的基础上,再实现返回栈中最小的元素的操作getmin,要求pop,push,getmin等操作的时间复杂度为O(1),可以使用系统已有的栈结构。
思路:
有两种方法:
第一种,创建两个栈结构,一个叫stackData用来存储例子中的数据,一个叫stackMin用来存储每一步(数据压入或者弹出)过程中stackData中的最小值,当stackData压入元素时,将元素和stackMin的栈顶元素进行比较,如果小于stackMin的栈顶元素,那么就将这个元素同样入stackMin这个栈,如果大于等于栈顶元素,则不压入;当stackData弹出元素时,比较弹出元素和stackMin的栈顶元素的大小,如果等于栈顶元素,则stackMin也弹出栈顶元素,弹出后stackMin的栈顶元素为stackData中的最小值,如果大于,则不弹出stackMin栈顶元素,此时stackMin的栈顶元素为stackData中的最小值。
第二种,也是创建两个栈结构,一个叫stackData一个叫stackMin。只是压入时,如果大于stackMin栈顶元素则stackMin压入栈顶元素,而不是第一种方法的不压,如果小于,则和第一种一样。弹出时不用判断,stackMin直接和stackData同时弹出就行了。
第一种方式和第二种方式的区别在于,方法一更加节省空间,方法二更加节省时间。
代码举例:
import java.util.Stack;
public class Solution {
private Stack<Integer> dataStack= new Stack<Integer>();
private Stack<Integer> minStack= new Stack<Integer>();
public void push(int node) {
dataStack.push(node);
if (minStack.empty() || minStack.peek() >= node) {
minStack.push(node);
} else {
// 方法一
// do nothing
// 方法二
//minStack.push(minStack.peek());
}
}
public void pop() {
if (dataStack.empty()) {
throw new RuntimeException("Your stack is empty!");
}
if (dataStack.peek() == minStack.peek()) {
minStack.pop();
}
dataStack.pop();
}
public int top() {
return dataStack.peek();
}
public int min() {
if (minStack.empty()) {
throw new RuntimeException("Your stack is empty!");
}
return minStack.peek();
}
}