中缀表达式就是:“数字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