利用栈Stack计算合法的算术表达式
限定的算术表达式求值问题:包含 “+”、“-”、“*”、“/” 、正整数和圆括号的合法算术表达式。
算术表达式转化成后缀表达式
程序语言中,运算符在两个运算数中间称为中缀表达式,即我们常用的表达方法,例如 1+2*3。
在中缀表达式中要考虑运算的优先级,先乘除,后加减,从左到右,还有括号内先运算。
在后缀表达式中已经考虑了运算符的优先级,并且没有括号,只有运算数和运算符。
例如上述例子 1+2*3 ,中缀表达式计算时,根据优先级,先计算2*3=6,再计算1+6=7
转换成后缀表达式 1+2*3 => 123*+ ,
从左到右扫描第一个运算符为 * ,先执行2*3;第二个运算符为 + ,执行1+6.
中缀表达式转后缀表达式过程
①初始化exp字符数组、resultExp字符数组(可变)、operator栈
exp字符数组:存放,合法的算术表达式
resultExp字符数组(可变):存放后缀表达式
operator栈:存放运算符,并将 “=” 作为栈底元素
②从exp读取字符ch,若为运算数将后续运算数依次存放入resultExp中,并以#标志数值结束
③若ch为运算符,将其和operator栈顶中的运算符进行比较优先级比较
ch优先级大于栈顶运算符优先级,则ch进栈
ch优先级小于栈顶运算符优先级,则栈中运算符退栈,直至ch运算符大于栈顶运算符,ch再进栈。
ch优先级等于栈顶运算符优先级,特殊情况,只有括号满足该情况,即“)”的优先级 等于“(”的优先级,将(退栈。
④exp扫描完毕,此时operator栈不空,则将 “=” 之前所有的运算符退栈并放入resultExp中
复杂一点的例子
(12-3)/(4+5)
算法如下:
package com.xumz.stack; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Stack; /** * 中缀表达式转后缀表达式 * * @author xumz 2017/10/18 */ public class ExpressionChange { // 存放左运算符的优先级 Map<Character, Integer> leftOperator = new HashMap<Character, Integer>() { { put('=', 0); put('(', 1); put('+', 3); put('-', 3); put('*', 5); put('/', 5); put(')', 6); } }; // 存放右运算符的优先级 Map<Character, Integer> rightOperator = new HashMap<Character, Integer>() { { put('=', 0); put('(', 6); put('+', 2); put('-', 2); put('*', 4); put('/', 4); put(')', 1); } }; /** * 中缀转后缀 * * @param str * @return */ public String trans(String str) { // 转换成char[] char[] exp = str.toCharArray(); // 存放转换结果 List<Character> resultExp = new ArrayList<Character>(); // 存放运算符,初始底为‘=’ Stack<Character> operator = new Stack<Character>(); operator.push('='); // 扫描exp表达式 int i = 0; while (i != exp.length) { // 数字情况 if (!isOperator(exp[i])) { while (i != exp.length && !isOperator(exp[i])) { resultExp.add(exp[i]); i++; } resultExp.add('#'); } // 运算符情况 else { switch (compareOperatorNice(operator.peek(), exp[i])) { case -1: operator.push(exp[i]); i++;// 继续下一个字符 break; case 0: operator.pop(); i++;// 继续下一个字符 break; case 1: resultExp.add(operator.peek()); operator.pop(); break; } } } while (!(operator.peek()=='=')) { resultExp.add(operator.peek()); operator.pop(); } // 转换为String返回 return resultExp.toString(); } boolean isOperator(char ch) { if (leftOperator.containsKey(ch)) { return true; } return false; } /** * 比较左右运算符优先级,返回状态结果 * * @param leftOperator * @param rightOperator * @return */ int compareOperatorNice(char left, char right) { if (leftOperator.get(left) == rightOperator.get(right)) { return 0; } if (leftOperator.get(left) < rightOperator.get(right)) { return -1; } return 1; } }