规则:
1、初始化两个栈:运算符栈s1和储存中间结果的栈s2
2、从左到右扫描中缀表达式;
3、遇到操作数,将其压s2;
4、遇到运算符时,比较其与s1栈顶运算符优先级:
1)、如果s1为空,或者栈顶运算符为左括号“(”,则直接将此运算符入栈;
2)、否则,若优先级比栈比栈顶运算符的高,也将运算符压放s1;
3)、否则,将s1栈顶的运算符弹出并压入到s2,再次转到4.1与s1中新的栈顶运算符想比较;
5、遇到括号时:
1)、如果是左括号“(”,则直接压入s1
2)、如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,此时将这一对括号丢弃
6、重复步骤2至5,直到表达式的最右边
7、将s1中剩余的运算符依次弹出并压入s2
8、依次弹出s2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式
package com.cn.test.algorithm;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class Nibolan2 {
public List<String> str2List(String str){
List<String> result = new ArrayList<>();
String letterMulti = "";
for (int i = 0;i<str.length();i++){
String letter = str.substring(i,i+1);
if(letter.matches("\\d")){
letterMulti+=letter;
}else{
if(letterMulti.length()>0){
result.add(letterMulti);
letterMulti = "";
}
result.add(letter);
}
}
if(letterMulti.length()>0){
result.add(letterMulti);
}
return result;
}
public List<String> list2Suffix(List<String> strList){
Stack<String> letterStack = new Stack<>();
List<String> result = new ArrayList<>();
for (String str:strList){
//操作数
if(str.matches("\\d+")){
result.add(str);
continue;
}
//左括号
if(str.equals("(")){
letterStack.push(str);
continue;
}
//左括号
if(str.equals(")")){
while(!letterStack.peek().equals("(")){
result.add(letterStack.pop());
}
letterStack.pop();
continue;
}
//运算符
if(letterStack.isEmpty() || letterStack.peek().equals("(")){
letterStack.push(str);
continue;
}
if(letterPriority(str)>letterPriority(letterStack.peek())){
letterStack.push(str);
}else{
while(!letterStack.isEmpty() && !letterStack.peek().equals("(") && letterPriority(str)<=letterPriority(letterStack.peek())){
result.add(letterStack.pop());
}
letterStack.push(str);
}
}
while (!letterStack.isEmpty()){
result.add(letterStack.pop());
}
return result;
}
public int letterPriority(String str){
switch (str){
case "+":
return 1;
case "-":
return 1;
case "*":
return 2;
case "/":
return 2;
}
throw new RuntimeException(str +" is not a letter");
}
public String calculate(List<String> suffixList){
Stack<String> calculateStack = new Stack<>();
String num1 = null;
String num2 = null;
for (String str:suffixList){
if(str.matches("\\d+")){
calculateStack.push(str);
}else{
num1 = calculateStack.pop();
num2 = calculateStack.pop();
calculateStack.push(calculateNum(num1,num2,str)+"");
}
}
return calculateStack.pop();
}
public int calculateNum(String num1,String num2,String letter){
switch (letter){
case "+":
return Integer.parseInt(num1)+Integer.parseInt(num2);
case "-":
return Integer.parseInt(num2) - Integer.parseInt(num1);
case "*":
return Integer.parseInt(num1) * Integer.parseInt(num2);
case "/":
return Integer.parseInt(num2)/Integer.parseInt(num1);
}
throw new RuntimeException(letter +" is not a letter");
}
public static void main(String[] args) {
Nibolan2 nibolan2 = new Nibolan2();
String str = "1+2+50*(5-4)*6-((6-1)+2+(9+6*2+9)/10-6)";
System.out.println("表达式:"+str);
List<String> strList = nibolan2.str2List(str);
System.out.println("表达式转的list:"+strList);
List<String> suffixList = nibolan2.list2Suffix(strList);
System.out.println("表达式转的后缀表达式:"+suffixList);
String result = nibolan2.calculate(suffixList);
System.out.println("计算结果 "+str + " = "+ result);
}
}
运算的结果:
表达式:1+2+50*(5-4)*6-((6-1)+2+(9+6*2+9)/10-6)
表达式转的list:[1, +, 2, +, 50, *, (, 5, -, 4, ), *, 6, -, (, (, 6, -, 1, ), +, 2, +, (, 9, +, 6, *, 2, +, 9, ), /, 10, -, 6, )]
表达式转的后缀表达式:[1, 2, +, 50, 5, 4, -, *, 6, *, +, 6, 1, -, 2, +, 9, 6, 2, *, +, 9, +, 10, /, +, 6, -, -]
计算结果 1+2+50*(5-4)*6-((6-1)+2+(9+6*2+9)/10-6) = 299