需求:计算算术表达式的值,例如:
解决方法: Dijkstra 用两个栈(一个是保存运算符,一个用于保存操作数)
流程:
算术表达式由括号、运算符和操作数组成。我们根据以下4种情况来实现。
1、将操作数压入操作数栈
2、将运算符压入运算符栈
3、忽略左括号
4、在遇到右括号时,弹出一个运算符,弹出所需数量的操作数,并将运算符和操作数的运算结果压入操作数栈。
算法实现轨迹:
代码实现如下:
import java.util.Stack;//Dijkstra的双栈算术表达式求值
public class Evaluate {
public static void main(String[] args) {
Stack<Character>ops = new Stack<Character>();//运算符下压栈
Stack<Double> vals = new Stack<Double>();//操作数下压栈
String str = "(1+((2+3)*(4*5)))";
String str1 = "((1+sqrt(5.0))/2.0)";
char[] arr = str.toCharArray();
for (char c : arr) {
if(c=='(') ;
else if(c=='+') {
ops.push(c);
}
else if(c=='-') {
ops.push(c);
}
else if(c=='*') {
ops.push(c);
}
else if(c=='/') {
ops.push(c);
}
else if((c+"").equals("sqrt")) {
ops.push(c);
}
else if(c==')') {
char op = ops.pop();
double v = vals.pop();
if(op=='+') {
v = vals.pop()+v;
}
else if(op=='-') {
v = vals.pop()-v;
}
else if(op=='*') {
v = vals.pop()*v;
}
else if(op=='/') {
v = vals.pop()/v;
}
else if((op+"").equals("sqrt")) {
v = Math.sqrt(v);
}
vals.push(v);
}
else {
vals.push(Double.parseDouble(c+""));
}
}
System.out.println(vals.pop());
}
}
案例通过如下:
;
但是若字符串输入改为String str1 = “((1+sqrt(5.0))/2.0)”;
若字符串中出现“sqrt”,挨个读取字符遇到s就直接判断,所以出问题!将代码改为如下情况,则可以得到正确结果
import java.util.Stack;//Dijkstra的双栈算术表达式求值
public class Evaluate {
public static void main(String[] args) {
Stack<String>ops = new Stack<String>();//运算符下压栈
Stack<Double> vals = new Stack<Double>();//操作数下压栈
String s1 = "( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )";
String s = "( ( 1 + sqrt ( 5.0 ) ) / 2.0 )";
String[] str = s.split(" ");
for (int i = 0; i < str.length; i++) {
if(str[i].equals("(")) ;
else if(str[i].equals("+")) {
ops.push(str[i]);
}
else if(str[i].equals("-")) {
ops.push(str[i]);
}
else if(str[i].equals("*")) {
ops.push(str[i]);
}
else if(str[i].equals("/")) {
ops.push(str[i]);
}
else if(str[i].equals("sqrt")) {
ops.push(str[i]);
}
else if(str[i].equals(")")) {
String op = ops.pop();
double v = vals.pop();
if(op.equals("+")) {
v = vals.pop()+v;
}
else if(op.equals("-")) {
v = vals.pop()-v;
}
else if(op.equals("*")) {
v = vals.pop()*v;
}
else if(op.equals("/")) {
v = vals.pop()/v;
}
else if(op.equals("sqrt")) {
v = Math.sqrt(v);
}
vals.push(v);
}
else {
vals.push(Double.parseDouble(str[i]));
}
}
System.out.println(vals.pop());
}
}
为了解决sqrt的问题,我们先对字符串进行spilt然后比较字符串的大小,注意要使用equals方法,这里若使用==,则出问题。