中缀表达式转后缀表达式(逆波兰表达式)
1.初始化一个栈和集合:运算符栈stack和储存中间结果的集合list;
2.从左至右扫描中缀表达式;
3.遇到操作数时,将其存入list;
4.遇到运算符时,比较其与stack栈顶运算符的优先级:
(1)如果stack为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
(2)否则,若优先级比栈顶运算符的高,也将运算符压入stack;
(3)否则,将stack栈顶的运算符弹出并存入到list中,再次转到步骤4.1与stack中新的栈顶运算符相比较;
5.遇到括号时:
(1)如果是左括号"(",则直接压入stack
(2)如果是右括号")",则依次弹出stack栈顶的运算符,并存入list,直到遇到左括号为止,此时将这一对括号丢弃
6.重复步骤2至5,直到表达式的最右边
7.将stack中剩余的运算符依次弹出并存入list
8.list中的元素即为中缀表达式对应的后缀表达式
中缀表达式转后缀表达式具体的实现可以参考网上资料,有许多在此不细说了。
本代码主要参考了尚硅谷的数据结构与算法课程,在其基础上做了一些改进。
可以满足整数的简单四则运算。
首先将中缀表达式从String转换为list,才好进行计算
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
public class ToSuffixExpression {
/**
* 将字符串表达式转换成list集合
* @param s
* @return 中缀表达式的list集合
*/
public static List<String> toInfixExpressionList(String s) {
List<String> list = new ArrayList<>();
//遍历字符串的指针
int i = 0;
//用来保存多位数
String str = "";
for (char c : s.toCharArray()) {
i++;
//用ASCII来匹配非数字字符,即运算符
if(c < 48 || c > 57){
//碰到运算符就将它的上一个多位数存进list
if(str != ""){
list.add(str);
str = "";
}
list.add("" + c);
}else{
str += c;
//最后一位字符是数字时,直接将str代表的多位数存入list
if(i == s.length()){
list.add(str);
}
}
}
return list;
}
/**
* 将中缀表达式换成后缀表达式
* @param ls
* @return 后缀表达式的list集合
*/
public static List<String> parseSuffixExpressionList(List<String> ls) {
//符号栈
Stack<String> stack = new Stack<>();
//后缀表达式栈,只用存数据,不需要pop操作,所以用list集合代替
ArrayList<String> list = new ArrayList<>();
for (String l : ls) {
//正则表达式匹配数字,存入到后缀表达式栈中
if(l.matches("\\d+")){
list.add(l);
}else if(l.equals("(")){
//左括号存入到符号栈中
stack.push(l);
}else if (l.equals(")")){
//如果是右括号,则依次弹出stack栈顶的运算符,并压入list,知道遇到左括号为止,然后将左括号弹出,完成去掉括号的操作
while(! (stack.peek().equals("("))){
list.add(stack.pop());
}
//弹出左括号,完成去掉括号的操作
stack.pop();
}else{
//当l运算符的优先级小于或等于stack栈顶运算符,将stack栈顶的运算符弹出并压入list中,再次转到4.1步骤中与stack中新的栈顶运算符相比较
//首先判断stack运算符栈不为空,然后写一个方法用来比较运算符优先级
while(stack.size() != 0 && getPriority(l) <= getPriority(stack.peek())){
list.add(stack.pop());
}
//l运算符优先级大于stack栈顶运算符,或stack运算符栈为空,直接将l压入stack中
stack.push(l);
}
}
//将stack中剩余的运算符依次弹出加入s2
while(! stack.isEmpty()){
list.add(stack.pop());
}
return list;
}
/**
* 获取运算符优先级的方法
* @param s
* @return 运算符优先级
*/
private static int getPriority(String s){
if("+".equals(s) || "-".equals(s)){
return 0;
}else if("*".equals(s) || "/".equals(s)){
return 1;
}
return -1;
}
}
到这里我们就获得了将中缀表达式转换成后缀表达式的方法,接下就是对后缀表达式进行计算,可以参考文章: