中缀表达式就是:“数字A 操作符 数字B” 这样的结构 ,例如:
A + B
A * B + C
就是 符号在两个数的中间
后缀表达式格式为: “数字A 数字B 操作符” 这样的结构 ,例如:
AB+
AB*C+
ABC+*
将后缀表达式 变为中缀表达式
AB+ --> A + B
AB*C+ --> A * B + C
ABC+* -- > A * (B + C)
如果给一个中缀表达式字符串,要计算其值 , 可以将其转换为后缀表达式 ,然后计算后缀表达式的值。
package com.zf.test; import java.util.regex.Matcher; import java.util.regex.Pattern; public class EndsExpression { private final String regexStr = "(\\([\\d\\.-]+?\\)|\\d)(\\([\\d\\.-]+?\\)|\\d)([*/+-])"; //计算后缀表达式的值 public String resove(String exp){ Matcher matcher = Pattern.compile(regexStr).matcher(exp); while(matcher.find()){ double first = Double.valueOf(replaceToNumeral(matcher.group(1))); double second = Double.valueOf(replaceToNumeral(matcher.group(2))); String oprator = matcher.group(3); double sum = calc(first , second , oprator); //计算结果 String sumStr = String.valueOf(sum); sumStr = sumStr.length() > 1 ? ( "(" + sumStr + ")" ) : sumStr; exp = exp.substring(0, matcher.end() - (matcher.group(1).length() + matcher.group(2).length() + 1 )) + sumStr + exp.substring(matcher.end(), exp.length()); matcher = Pattern.compile(regexStr).matcher(exp); } return replaceToNumeral(exp) ; } // 将 (12) 这中值 变成 12 ,去掉其中的() 符号 , 使其变为数字格式 public String replaceToNumeral(String str){ return str.replace("(", "").replace(")", ""); } //根据两个数 和 一个操作符计算 public double calc(double first , double second , String oprator){ if(oprator.equals("+")){ return first + second; }else if(oprator.equals("-")){ return first - second; }else if(oprator.equals("*")){ return first * second; }else if(oprator.equals("/")){ return first / second; }else{ return 0 ; } } //中缀表达式转换为后缀表达式 public String transForm(String middleExp){ String regStr = "\\d+\\.\\d+|\\d+|[+-/*\\()]"; Pattern pattern = Pattern.compile(regStr); Matcher matcher = pattern.matcher(middleExp); StringBuffer endExp = new StringBuffer(); //后缀表达式 StackX<String> stack = new StackX<String>(100); //操作符栈 while(matcher.find()){ String current = matcher.group(); current = current.length() > 1 ? ( "(" + current + ")" ) : current; if(current.matches("[+-/*\\()]")){ if(stack.isEmpty()){ //栈为空 ,直接推入 stack.put(current); }else{ if(current.equals(")")){ String top = stack.pop() ; //推出栈顶 操作符 while(!top.equals("(")){ endExp.append(top); top = stack.pop(); } }else{ String top = stack.pop() ; //推出栈顶 操作符 if(top.equals("(") || compareOprator(current , top) > 0){ //当前操作符比 栈顶操作符大 , 就推入栈顶 stack.put(top); }else{ //当前操作符 <= 栈顶操作符 endExp.append(top); } stack.put(current); } } }else{ //常数 endExp.append(current); } } while(!stack.isEmpty()) endExp.append(stack.pop()); return endExp.toString() ; } //比较操作符优先级 public int compareOprator(String op1 , String op2){ if(op1.matches("[+-]")){ if(op2.matches("[+-]")){ return 0; }else{ return -1 ; } }else if(op1.matches("/*")){ if(op2.matches("[/*]")){ return 0; }else if(op2.matches("[+-]")){ return 1 ; }else{ return -1 ; } }else{ if(op2.matches("[\\()]")){ return 0; }else{ return 1 ; } } } public static void main(String[] args) { EndsExpression e = new EndsExpression(); String middleExps[] = new String[]{ "12 + 2-21" ,"100*3 + 31 - 1 " ,"12 * 3 + ( 1 - 2 * 2 )" ,"20 * 2 + (2.31 - 1)*2 + 2" }; for (String middleExp : middleExps) { String endExp = e.transForm(middleExp); String result = e.resove(endExp); System.out.printf("中缀表达式%1$s\t转换为后表达式为:%2$s\t计算后缀表达式结果为:%3$s\n" , middleExp , endExp , result); } } }
使用到的工具类:
package com.zf.test; public class StackX<T> { private int maxLengh ; private int top ; private Object[] array ; public StackX(int maxLengh){ this.maxLengh = maxLengh ; this.array = new Object[maxLengh]; this.top = -1 ; } public int size(){ return this.top ; } public void put(T entry){ if(isFull()) throw new ArrayIndexOutOfBoundsException("array is fully!"); array[++top] = entry ; } @SuppressWarnings("unchecked") public T pop(){ if(isEmpty()) throw new ArrayIndexOutOfBoundsException("array is empty!"); return (T)array[top--]; } public boolean isEmpty(){ return top == -1 ; } public boolean isFull(){ return top == maxLengh - 1; } }
结果:
中缀表达式12 + 2-21 转换为后表达式为:(12)2+(21)- 计算后缀表达式结果为:-7.0 中缀表达式100*3 + 31 - 1 转换为后表达式为:(100)3*(31)+1- 计算后缀表达式结果为:330.0 中缀表达式12 * 3 + ( 1 - 2 * 2 ) 转换为后表达式为:(12)3*122*-+ 计算后缀表达式结果为:33.0 中缀表达式20 * 2 + (2.31 - 1)*2 + 2 转换为后表达式为:(20)2*(2.31)1-2*2++ 计算后缀表达式结果为:44.62