后缀表达式 (又称 逆波兰表达式) Java代码的简单实现
表达式求值问题
好久没有发随笔了,最近学习复习数据结构的时候看到了后缀表达式(逆波兰表达式)
发现了栈的精巧,自己想实现一下,本来想用C写的,但是实在太困难了,所有写了个简单的Java版本,还可以的
输入中缀表达式 可以得到计算结果
- 中缀表达式
- 后缀表达式 (又称 逆波兰表达式)
- 前缀表达式(又称 波兰表达式)
中缀表达式 | 后缀表达式 | 前缀表达式 |
---|---|---|
a+b | ab+ | +ab |
a+b-c | ab+c- | -+abc |
a+b-c*d | ab+cd*- | -+ab*cd |
利用栈实现输入中缀字符串完成后缀计算
Java代码
由于c代码不好字符串转小数,也不好记录连续的数字,所有采用java实现;这里只涉及+ - * /(加减乘除)
package com.mhy.calculate;
import java.util.ArrayDeque;
import java.util.Deque;
public class Calculate {
public static void main(String[] args) {
Calculate calculate = new Calculate();
String str = "11.2*88.9-(5*8+83.5-99)+55-88/44-(8+2-3+(55*8))-11.18-46+1";
System.out.println(calculate.calculate(str));
//521
}
public double calculate(String str){
int nums = 0;//记录数字个数
int length = str.length();//字符串的长度
Deque<Double> numQ = new ArrayDeque<>();//数字栈
Deque<Character> charQ = new ArrayDeque<>();//符号栈
for (int i = 0; i < length; i++) {
char x = str.charAt(i);
if(isNum(x)){//如果x是数或者小数点
nums++;
}else {
if(nums != 0){//数字入栈
double v = Double.parseDouble(str.substring(i - nums, i));//截取小数
numQ.offerFirst(v);//数字入栈
}
nums = 0;//重置记录个数
if(x == '('){//判断是否为'(',
charQ.offerFirst(x);
continue;
}else if(charQ.isEmpty()){//判断是否为空
charQ.offerLast(x);
continue;
}
while(true){//符号栈的弹出操作
if(charQ.isEmpty()) {//如果为空了
if(x != ')'){//并且这个字符不是')'就入栈
charQ.offerFirst(x);
}
break;//结束循环
}
char y = charQ.peekFirst();//获取符号的栈顶元素
if(y == '(' && x == ')') {//如果栈顶为'(' 且 需要入栈的是')'
charQ.pollFirst();//就直接'('弹出栈,')'不入栈
break;//结束循环
}
if(y == '(' && x != ')'){//如果栈顶为'(' 且 需要入栈的不是')'
charQ.offerFirst(x);//直接入栈
break;//结束循环
}
if(x == ')'){//如何入栈的是')' 开始弹栈进行运算
char p = charQ.pollFirst();//栈顶符号
double b = numQ.pollFirst();//后操作数
double a = numQ.pollFirst();//前操作数
numQ.offerFirst(cal(a,b,p));//结果入栈
continue;
}
if(operatorsRules(x,y)){//如果不是')',就符号比较,大于等于就运算
charQ.pollFirst();
double b = numQ.pollFirst();
double a = numQ.pollFirst();
numQ.offerFirst(cal(a,b,y));
}else {//否则符号入栈
charQ.offerFirst(x);
break;
}
}
}
}
if(nums != 0){//数字入栈 由于中缀输入都是以数字结尾,所以最后还需要进行运算
double v = Double.parseDouble(str.substring(length - nums, length));
numQ.offerFirst(v);
}
while(!charQ.isEmpty()){//把符号栈谈完
char p = charQ.pollFirst();
double b = numQ.pollFirst();
double a = numQ.pollFirst();
numQ.offerFirst(cal(a,b,p));
}
return numQ.pollFirst();//最好数字栈的栈顶就是结果
}
//是否为数
public boolean isNum(char x){
if(x == '.') return true;
return x >= 48 && x <= 57;
}
//计算
public Double cal(double a,double b,char x){
if(x == '*') return a*b;
if(x == '/') return a/b;
if(x == '-') return a-b;
if(x == '+') return a+b;
return null;
}
//符号优先级判断
public boolean operatorsRules(char x,char y){
if(x == '*' || x== '/'){
if(y == '*') return true;
else if(y == '/') return true;
else if(y == '+') return false;
else if(y == '-') return false;
}
if(x == '+' || x == '-'){
if(y == '-') return true;
else if(y == '+') return true;
else if(y == '*') return true;
else if(y == '/') return true;
}
System.out.println("符号输入错误");
return false;
}
}