前缀,中缀,后缀表达式
前缀表达式(波兰表达式):
运算符位于操作数之前,(3+4)*5-6对应的是- * + 3 4 5 6
计算机求值:从右向左扫描表达式,遇到数字时,将数字压入栈;遇到运算
符时,弹出栈顶两个元素(先弹出的-后弹出的),用运算符对他们进行运
算,并将结果入栈,直至过程到达表达式最左端。
中缀表达式:
最常见的运算表达式
计算机操作时,一般会将其转换为后缀表达式来操作。
后缀表达式(逆波兰表达式):
运算符位于操作符号之后,(3+4)*5-6对应的是3 4 + 5 * 6 –
计算机求值:从左向右扫描表达式,遇到数字时,将数字压入
栈;遇到运算符时,弹出栈顶的两个数,用运算符对他们进行
计算(后弹出的-先弹出的),并将结果入栈,直到扫描完毕
整个表达式。
逆波兰表达式计算器:
使用栈来进行计算
package com.dataStructure;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class stackPoland {
public static void main(String[] args){
String inputPoland = "30 4 + 5 * 6 -";
System.out.println("当前list为:");
System.out.println(list(inputPoland));
System.out.println("运算结果为:");
System.out.println(calculate(list(inputPoland)));
}
public static List<String> list (String inputPoland){
String[] split = inputPoland.split(" ");
List<String> tempList = new ArrayList<String>();
for(String ele:split){
tempList.add(ele);
}
return tempList;
}
public static int calculate(List<String> inputPoland){
Stack<String> stack = new Stack<String>();
for(String ele: inputPoland) {
if (ele.matches("\\d+")) {
//匹配的是多位数
stack.push(ele);
} else {
int num1 = Integer.parseInt(stack.pop());
int num2 = Integer.parseInt(stack.pop());
int res = 0;
if (ele.equals("+")){
res = num1+num2;
}else if(ele.equals("-")){
res = num2-num1;
}else if(ele.equals("*")){
res = num1*num2;
}else if(ele.equals("/")){
res = num2/num1;
}else{
throw new RuntimeException("输入有误!");
}
stack.push(res+"");
//遍历栈,查看当前情况
}
}
return Integer.parseInt(stack.pop());
}
}
中缀表达式转后缀表达式
思路:
1. 初始化两个栈,储存运算符的栈s1和储存中间结果的栈s2
2. 从左至右扫描中缀表达式,直到表达式的最右边
a) 遇到操作数时,将其压入s2.
b) 遇到运算符时,比较其与s1栈顶的运算符优先级
i. 如果s1为空,或者栈顶运算符为左括号(,直接将此运算符入栈
ii. 否则,如果优先级比栈顶运算符高,也将运算符压入s1
iii. 否则,将s1栈顶的运算符弹出压入s2中,再次将新运算符送至2-b-i步骤,与栈顶运算符相比较
c) 遇到括号时
i. 如果是左括号( ,直接压入s1
ii. 如果是右括号 ),则一次弹出s1栈顶的运算符,并压入s1,直到遇到左括号为止,并将这一对括号丢弃
3. 将s1中剩余的运算符依次弹出并压入s2
4. S2中的逆序输出就是后缀表达式