后缀表达式是什么?
后缀表达式也是逆波兰表达式,而波兰表达式就是前缀表达式。
一个表达式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、创建一个栈
2、循环扫描后缀表达式
3、当扫描到的是数字时,直接压入栈中
4、当扫描到运算符时,从栈中取出栈顶元素和次顶元素与该运算符进行计算
4.1、如果运算符是➖或者➗要用栈中的次顶元素➖(➗)栈顶元素
5、将计算结果再压入栈中
6、重复3~5步,直到扫描完整个表达式,最后栈中的一个元素就是表达式的最终结果。
代码实现:
public class PolandNotation {
public static void main(String[] args) {
//定义一个逆波兰表达式
// (3+4)*50-6 => 3 4 + 50 * 6 -
// 4.8*5.5-8+60+8/2 => 4.8 5.5 * 8 - 60 + 8 2 / +
// 为了方便,逆波兰表达式的数字和符号用一个空格隔开
String suffixExpression = "4.8 5.5 * 8 - 60 + 8 2 / +";
//将表达式存储在ArrayList中
List<String> list;
list = getListString(suffixExpression);
System.out.println(list);
//调用方法计算逆波兰表达式
System.out.printf("表达式%s = %f", suffixExpression, lastPolandExpression(list));
}
//判断是不是运算符
public static boolean isOper(char val){
return val == '+' || val == '-' || val == '*' || val == '/';
}
/**
* 计算逆波兰表达式
* @param list 用来存储表达式
* @return 返回最终计算结果
*/
public static double lastPolandExpression(List<String> list) {
//创建一个栈
Stack<String> stack = new Stack<>();
//遍历存储表达式的list集合
for (int i = 0; i < list.size(); i++) {
char s = list.get(i).charAt(0);
if (!isOper((s))) {
//如果是数字
String str = list.get(i);
//入栈
stack.push(str);
}else {
//如果是运算符,取出栈顶元素和次顶元素进行计算
double num1 = Double.parseDouble( stack.pop() );
double num2 = Double.parseDouble( stack.pop() );
double result = cal(num1,num2,s);
//最后将计算结果压入栈中
stack.push(String.valueOf(result));
}
}
//返回栈中的最后一个元素,就是计算结果
return Double.parseDouble( stack.pop() );
}
public static double cal(double num1,double num2,int oper){
double res = 0; // 存放计算结果
switch (oper){
case '+':
res = num1 + num2;
break;
case '-':
res = num2 - num1;
break;
case '*':
res = num1 * num2;
break;
case '/':
if (num1 == 0)
throw new RuntimeException("0不能作为除数!");
res = num2 / num1;
break;
default:
break;
}
return res;
}
public static List<String> getListString(String suffixExpression) {
// 将suffixExpression按照空格分割
String[] split = suffixExpression.split(" ");
List<String> list = new ArrayList<>();
for (String ele : split) {
list.add(ele);
}
return list;
}
}