从前面栈实现综合计算器(中缀表达式)和逆波兰(后缀表达式)计算器两节中可以看出,后缀表达式适合计算机进行计算,但是写法复杂,难以看懂,中缀表达式适合人类读懂,但是不适合计算机进行计算,那么我们就需要搭桥,让中缀表达式转成后缀表达式,以方便计算机计算。
- 中缀表达式转换为后缀表达式步骤:
初始化两个栈 S1(存储运算符)和S2(存储结果)
从左到右遍历中缀表达式:
若取出的字符是操作数:将操作数压入S2;
若取出的字符是运算符:
若S1为空栈: 取出的字符入S1栈;
若S1栈顶运算符是左括号:取出的字符入S1栈;
若取出的字符运算符比S1栈顶的运算符优先级高:取出的字符入S1栈;
否则将S1栈顶的运算符弹出并压入S2中;
若取出的字符是括号:
若取出的字符是左括号,直接入S1栈;
若取出的字符是 右括号,则依次弹出S1栈的运算符,并压入S2,直到遇到左括号为止,此时一对括号丢弃;
直到表达式遍历完毕,则将S1中剩余的运算符依次弹出并压入S2,
最终S2中逆序输出的为后缀表达式。
举例 中缀表达式转后缀表达式
举例 代码实现
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
/**
* 逆波兰表达式计算器
*/
public class PolandNotation {
public static void main(String[] args) {
List<String> infixExpression = toInfixExpressionList("1+((2+3)*4)-5");
System.out.println("中缀表达式 : "+infixExpression);
List<String> parseSuffixExpression = parseSuffixExpressionList(infixExpression);
System.out.println("后缀表达式 : "+parseSuffixExpression);
int result = calculate(parseSuffixExpression);
System.out.println("计算结果为:"+result);
}
/**
* 将表达式转化为中缀表达式
* @param expression 表达式
* @return
*/
public static List<String> toInfixExpressionList(String expression){
List<String> list = new ArrayList<String>();
int index = 0;
while(index < expression.length()){
char ch = expression.charAt(index);
if((ch < 48) || (ch > 57)){//当前字符非数字
list.add(ch+"");
index++;
}else{//当前字符是数字
String str = "";
//查看当前字符下一位是不是数字
while (index<expression.length() && expression.charAt(index) >= 48 && expression.charAt(index) <= 57){
str += ch;
index++;
}
list.add(str);
}
}
return list;
}
/**
* 将中缀表达式转化为后缀表达式
* @param list
* @return
*/
public static List<String> parseSuffixExpressionList(List<String> list){
Stack<String> stack1 = new Stack<>();
Stack<String> stack2 = new Stack<>();
for (String item : list){
if (item.matches("\\d+")){//数字
stack2.push(item);
}else if(item.equals("(")){//左括号
stack1.push(item);
}else if(item.equals(")")){//右括号
//右括号,则依次弹出S1栈的运算符,并压入S2,直到遇到左括号位置,此时一对括号丢弃
while (!stack1.peek().equals("(")){
stack2.push(stack1.pop());
}
stack1.pop();
}else{//当前字符为运算符
while (!stack1.empty() && operationPriority(stack1.peek()) >= operationPriority(item)){
stack2.push(stack1.pop());
}
stack1.push(item);
}
}
while (!stack1.empty()){
stack2.push(stack1.pop());
}
return stack2;
}
/**
* 完成后缀表达式的计算
* @param list
* @return
*/
public static int calculate(List<String> list){
//创建栈 用于存放数据
Stack<String> stack = new Stack<String>();
//对存入后缀表达式的ArrayList进行遍历
for (String item : list){
//如果是数字 则入栈
if(item.matches("\\d+")){//匹配数字
stack.push(item);//入栈
}else {//如果不是数字 则出栈两个数字 和当前符号进行计算 将计算结果入栈
int num1 = Integer.parseInt(stack.pop());
int num2 = Integer.parseInt(stack.pop());
int sum = 0;
if (item.equals("+")){
sum = num2 + num1;
}
if (item.equals("-")){
sum = num2 - num1;
}
if (item.equals("*")){
sum = num2 * num1;
}
if (item.equals("/")){
sum = num2 / num1;
}
stack.push(sum+"");
}
}
//栈中剩余的最后一个数组则为计算结果
return Integer.parseInt(stack.pop());
}
/**
* 操作符的优先级
* @param operation true 表示乘除
* @return
*/
public static int operationPriority(String operation){
int result = 0;
switch (operation) {
case "+":
result = 1;
break;
case "-":
result = 1;
break;
case "*":
result = 2;
break;
case "/":
result = 2;
break;
default:
//System.out.println("不存在该运算符" + operation);
break;
}
return result;
}
}