对于计算机来说,后缀表达式更方便计算,但是对于我们来说,中缀表达式更方便理解。为了大家都方便,下面就聊聊如何把一个中缀表达式借助代码转化成一个后缀表达式。
在实现转后缀表达式时,用栈结构存储操作符,由于中间结构不用出栈,并且如果用栈结构存储,那么将出栈结果逆序才是我们要的后缀表达式,所以用List存储即可,下面先来说说转化过程的思路:
- 若当前元素是数字,直接入list;
- 若当前元素是左括号(,直接入stack;
- 若当前元素是右括号),将stack中的元素出栈,并入list中,直到遇到左括号停止,并将左括号出栈(这里舍弃一对括号);
- 此时,当前元素是操作符,如果当前操作符的优先级小于或者等于栈顶操作符优先级,出栈并将出栈的操作符入list,再将当前操作符入栈;否则直接入栈。
代码:
//把中缀表达式转化成对应的后缀表达式
public class InfixToSuffix {
public static void main(String[] args) {
String expre = "1+((2+3)*4)-5";
List<String> list = infixToList(expre);
System.out.println("中缀list="+list);
List<String> list1 = toSuffix(list);
System.out.println("后缀list="+list1);
}
//把中缀表达式字符串转成对应的list
public static List<String> infixToList(String str){
int i =0;
char ch;
String s;
List<String> list = new ArrayList<>();
do {
if ((ch = str.charAt(i))<48 || (ch = str.charAt(i))>57){
//是操作符,直接放入list中
list.add(""+ch);
i++;
}else {
s = "";//每次都要初始化为空字符串
while (i<str.length()&&((ch = str.charAt(i))>=48 && (ch = str.charAt(i))<=57)){
s += ch;
i++;
}
list.add(s);
}
}while (i<str.length());
return list;
}
/**
* 将传入的list转成后缀list
* @param list
* @return
*/
public static List<String> toSuffix(List<String> list){
//用来存放操作符的
Stack<String> stack = new Stack<>();
//用来存放中间过程
List<String> ls = new ArrayList<>();
for (String item : list){
//遍历传入的集合,数字存入ls,操作符存入stack
if (item.matches("\\d+")){
ls.add(item);
}else if (item.equals("(")){
stack.push(item);
}else if (item.equals(")")){
while (!stack.peek().equals("(")){
ls.add(stack.pop());
}
//去掉stack中的(
stack.pop();
}else {
while (stack.size()!=0 && (Operation.getVal(stack.peek()))>=(Operation.getVal(item))){
//当前操作符的优先级小于或等于栈顶操作符优先级
ls.add(stack.pop());
}
//
stack.push(item);
}
}
//遍历完list,还需将stack中剩余元素加入ls中
while (stack.size()!= 0){
ls.add(stack.pop());
}
return ls;
}
}
class Operation{
public static int getVal(String s){
int res =0;
switch (s){
case "+":
res = 1;
break;
case "-":
res = 1;
break;
case "*":
res = 2;
break;
case "/":
res = 2;
break;
default:
break;
}
return res;
}
}