来源:https://www.bilibili.com/video/BV1B4411H76f?p=39
一、思路
1、初始化同样设置两个栈,符号栈s1和结果栈s2;
2、从左到右扫描中缀表达式;
3、遇到数据,直接入栈s2;
4、遇到符号:
4.1、如果s1为空,或者s1的栈顶符号为 "(" ,也就是左括号,直接入栈s1
4.2、如果当前符号比s1栈顶的符号优先级高,直接入栈s1
4.3、否则,将s1栈顶的那个运算符弹出,压入到s2,然后回到4.1继续比较,直到入栈。
5、遇到括号:
5.1、左括号"("直接入栈s1
5.2、右括号")",将s1中的运算符依次弹出,入栈s2,直到遇到左括号"(",此时将括号删除
6、重复步骤2-5,直到表达式结束
7、将s1中剩余的符号弹出,入栈s2
8、s2中的内容依次弹出,逆序,则为后缀表达式
二、实现
1、根据原始字符串的到中缀表达式对应的数组,要注意多位数的存在
1 //根据原始字符串得到中缀表达式的字符串 2 public static List<String> getInfixArray(String s){ 3 List<String> list = new ArrayList<>(); 4 int i = 0;//遍历原始的表达式 5 char c;//获取当前位置的字符 6 String keepNum;//如果是多位数可以用来拼接 7 while (true){ 8 if((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57){ 9 //不是数字 10 list.add(""+c); 11 i++; 12 }else { 13 keepNum = ""; 14 while (i < s.length() && (c = s.charAt(i))>= 48 && (c = s.charAt(i)) <= 57 ){ 15 keepNum += c; 16 i++; 17 } 18 list.add(""+keepNum); 19 } 20 if(i > s.length() - 1){ 21 break; 22 } 23 } 24 return list; 25 }
测试
1 //原始表达式 2 String expression = "1+((2+3)*4)-5"; 3 //根据原始表达式得到中缀表达式 4 List<String> infixArray = getInfixArray(expression); 5 System.out.println(infixArray);
结果
[1, +, (, (, 2, +, 3, ), *, 4, ), -, 5]
2、按照思路将中缀表达式转化为后缀表达式(这里为了方便,将结果栈s2定义为数组,不必进行弹出后再倒序)。同时,定义了一个判断符号优先级的方法。
1 public static List<String> infixToSuffix(List<String> infix){ 2 //符号栈 3 Stack<String> s1 = new Stack<String>(); 4 //结果,由于后期需要逆序得到结果,这里用数组 5 List<String> s2 = new ArrayList<>(); 6 7 for (String item : infix) { 8 if(item.matches("\d+")){ 9 //如果是一个数字 10 s2.add(item); 11 }else if(item.equals("(")){ 12 //左括号,入符号栈 13 s1.push(item); 14 }else if(item.equals(")")){ 15 //右括号,直到找到左括号 16 while (!s1.peek().equals("(")){ 17 s2.add(s1.pop()); 18 } 19 s1.pop();//弹出左括号 20 }else { 21 //不为空,且优先级小于等于栈顶的 22 while (s1.size() != 0 && properties(item) <= properties(s1.peek())){ 23 s2.add(s1.pop()); 24 } 25 //否则,直接入栈 26 s1.push(item); 27 } 28 } 29 30 //表达式遍历完成,s1出栈加入到s2 31 while (!s1.isEmpty()){ 32 s2.add(s1.pop()); 33 } 34 return s2; 35 } 36 37 //计算符号的优先级 38 public static int properties(String oper){ 39 int res = 0; 40 switch (oper){ 41 case "+": 42 res = 1; 43 break; 44 case "-": 45 res = 1; 46 break; 47 case "*": 48 res = 2; 49 break; 50 case "/": 51 res = 2; 52 break; 53 default: 54 System.out.println("运算符错误"); 55 break; 56 } 57 return res; 58 }
测试
1 //中缀转后缀 2 List<String> suffix = infixToSuffix(infixArray); 3 System.out.println(suffix); 4 System.out.println(); 5 6 int res = calculate(suffix); 7 System.out.println(res);
结果
运算符错误 运算符错误 [1, 2, 3, +, 4, *, +, 5, -] 16