后缀表达式是什么?
后缀表达式也是逆波兰表达式,而波兰表达式就是前缀表达式。
一个表达式E的后缀形式可以如下定义:
(2)如果E是E1 op E2形式的表达式,这里op是任何二元操作符,则E的后缀式为E1'E2' op,这里E1'和E2'分别为E1和E2的后缀式。
(3)如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。
如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+
(a+b)*c-(a+b)/e的后缀表达式为:
(a+b)*c-(a+b)/e
→((a+b)*c)((a+b)/e)-
→((a+b)c*)((a+b)e/)-
→(ab+c*)(ab+e/)-
→ab+c*ab+e/-
直接用明确的表达式可能更好理解如:
4 * 5 - 8 + 60 + 8 / 2(中缀) => 4 5 * 8 - 60 + 8 2 / +(后缀)
因为中缀表达式是人们常用的表达式,对应人来说很方便,但是对应计算机来说处理起来比较复杂
所以我们需要将中缀表达式转换成后缀表达式。
带括号的中缀表达式转换成后缀表达式后是没有括号存在的。
解决思路
1)初始化一个栈和一个集合:运算符栈operStack和储存中间结果的集合resList; 2)从左至右扫描中缀表达式; 3)遇到操作数时,将其加入resList; 4)遇到运算符时,比较其与operStack栈顶运算符的优先级: 4.1.如果operStack为空,或栈顶运算符为左括号,则直接将此运算符入栈; 4.2.否则,若优先级比栈顶运算符的高,也将运算符压入operStack; 4.3.否则,将operStack栈顶的运算符弹出并压入到resList中,再次转到(4.1)与operStack中新的栈顶运算符相比较; 5)遇到括号时: 5.1如果是左括号“(”, 则直接压入栈中 5.2如果是右括号“)”,则依次弹出operStack栈顶的运算符,并压入resList,直到遇到左括号为止,此时将这一对括号丢弃!!! 6)重复步骤2至5,直到表达式的最右边 7)将operStack中剩余的运算符依次弹出并压入resList 8)依次弹出resList中的元素并输出,结果的逆即为中缀表达式对应的后缀表达式
完整代码实现
/**
* 实现将中缀表达式转换位后缀表达式
* 4 * 5 - 8 + 60 + 8 / 2(中缀) => 4 5 * 8 - 60 + 8 2 / +(后缀)
* 1 + ( ( 2 + 3 ) * 4 ) - 5(中缀) => 1 2 3 + 4 * + 5 -(后缀)
*/
public class InfixExpressionToSuffixExpression {
public static void main(String[] args) {
//定义一个中缀表达式
String infixExp = "1 + ( ( 2 + 3.5 ) * 4 ) - 5";
//将中缀表达式存储在ArrayList中
List<String> list;
list = getListString(infixExp);
//定义要转换成的后缀表达式
List<String> suffixExp = infixExpToSuffixExp(list);
System.out.println(suffixExp);
}
public static List<String> infixExpToSuffixExp(List<String> infixExp){
//创建一个用来存储运算符的stack
Stack<String> operStack = new Stack<>();
//创建一个用来临时存储计算结果的operList
List<String> resList = new ArrayList<>();
//遍历infixExp
for (String item : infixExp) {
//如果是一个数,加入resList
// 匹配正数,负数,小数的正则表达式: ^(\-|\+)?\d+(\.\d+)?$
if (item.matches("^(\\-|\\+)?\\d+(\\.\\d+)?$")){
resList.add(item);
} else if (item.equals("(")) {
operStack.push(item);
} else if (item.equals(")")) {
//如果是又括号,则依次弹出operStack中的运算符,并压入resList,直到遇到左括号为止,此时将这对括号丢弃
while (!operStack.peek().equals("(")){
resList.add(operStack.pop());
}
operStack.pop(); // 消除左括号!!!
}else {
//当item的优先级小于等于栈顶的优先级时
while ( operStack.size() != 0 &&
priority( item.charAt(0) ) <= priority( operStack.peek().charAt(0) ) ) {
resList.add(operStack.pop());
}
//还要将item压入栈
operStack.push(item);
}
}
///将operStack中剩余的运算符依次加入resList中
while (operStack.size() != 0){
resList.add(operStack.pop());
}
return resList;
}
//返回运算符的优先级,用数字表示
public static int priority(int oper){
if (oper == '*' || oper == '/')
return 1;
if (oper == '+' || oper == '-')
return 0;
return -1;
}
public static List<String> getListString(String infixExpression) {
// 将suffixExpression按照空格分割
String[] split = infixExpression.split(" ");
List<String> list = new ArrayList<>();
for (String ele : split) {
list.add(ele);
}
return list;
}
}
以上代码中的表达式需要用一个空格分开,否则可能会出现异常。