栈和队列的前世今生
栈和队列的定义
栈【Stack】在一端并且是同一端进行插入或者删除的线性表,可以使用数组或者链表实现,遵循的是FILO先进后出
,或者是后进先出的原则,在现实生活类似肠子就是线性表,吃完就吐就是栈。
队列【Queue】在一端进行插入,另外一端进行删除的线性表,可以使用数组和链表实现,遵循FIFO先进先出
的原则。在现实生活类似肠子就是线性表,吃完就蹲坑就是队列。
代码定义
栈
#define MAXSIZE 50
typedef int ElemType;
typedef struct{
ElemType data[MAXSIZE];
int top;
}SqStack;
队列
#define MAXSIZE 50
typedef struct{
ElemType data[MAXSIZE];
int front,rear;
}SqQueue;
在 java 中栈和队列
栈和队列是一种数据结构,满足和维护这种数据结构都可以作为栈和队列的实现方式
推荐使用,原因是这些实现类功能更加的强大,性能更加的优秀,左父有子体现了多态性
栈,push压栈,pop出栈,peek查询
Deque<Integer> stack = new LinkedList<>();
队列,offer出队,poll出队,peek
Queue<Integer> queue = new ArrayDeque<>();
堆
用于实现小顶堆,默认头部最小
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>();
大顶堆
重写compare方法
PriorityQueue<Integer> bigHeap = new PriorityQueue<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2-o1;
}
});
lambda表达式实现
Queue<Integer> bigHeap = new PriorityQueue<>((o1, o2) -> o2 - o1);
后缀表达式
根据 逆波兰表示法,求该后缀表达式的计算结果。
有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
解题思路
后缀表达式严格遵循「从左到右」的运算。计算后缀表达式的值时,使用一个栈存储操作数,从左到右遍历后缀表达式,进行如下操作:
- 如果遇到操作数,则将操作数入栈;
- 如果遇到运算符,则将两个操作数出栈,其中
先出栈的是右操作数
,后出栈的是左操作数
,使用运算符对两个操作数进行运算,将运算得到的新操作数入栈
。 - 整个后缀表达式遍历完毕之后,栈内只有一个元素,该元素即为后缀表达式的值。
代码如下
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList<>();
int n = tokens.length;
for(int i = 0; i < n; i++){
String token = tokens[i];
if(isNumber(token)){
stack.push(Integer.parseInt(token));
}else{
// 先出来的作为第二个操作数
int num2 = stack.pop();
int num1 = stack.pop();
switch(token){
case "+":
stack.push(num1 + num2);
break;
case "-":
stack.push(num1 - num2);
break;
case "*":
stack.push(num1 * num2);
break;
case "/":
stack.push(num1 /num2);
break;
default:
}
}
}
// 栈中最后的一个操作数就是后缀表达式的结果
return stack.pop();
}
public static boolean isNumber(String token){
return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));
}