要求:编程模拟(1+(2+3)*(4*5))的运算过程,重点在于如何解析由括号运算符和数字组成的字符串,并按照正确的顺序完成各种初级运算符的操作。
实现思路:用两个栈(LIFO)结构来实现(一个用于保存运算符,一个用于保存操作数)
- 将操作数压如操作数栈
- 将操作符压如操作符栈
- 忽略左括号
- 在遇到右括号时,弹出一个运算符,并弹出所需数量的操作数,并将操作符和操作数的运算结果压到操作数栈
1 package com.luochuang.demo.stdlib; 2 3 public class Evalute { 4 public static void main(String[] args) { 5 Stack<String> ops = new Stack<String>(); 6 Stack<Double> vas = new Stack<Double>(); 7 while (!StdIn.isEmpty()) { 8 //读取字符,如果是运算符则压入栈 9 String s = StdIn.readString(); 10 if (s.endsWith("(")) { 11 } else if (s.endsWith("+")) { 12 ops.push(s); 13 } else if (s.endsWith("-")) { 14 ops.push(s); 15 } else if (s.endsWith("*")) { 16 ops.push(s); 17 } else if (s.endsWith("/")) { 18 ops.push(s); 19 } else if (s.endsWith("sqrt")) { 20 ops.push(s); 21 } else if (s.endsWith(")")) { 22 // 当遇到右操作数,弹出一个运算符 23 String op = ops.pop(); 24 double v = vas.pop(); 25 if (op.endsWith("+")) { 26 v = vas.pop() + v; 27 } else if (op.endsWith("-")) { 28 v = vas.pop() - v; 29 } else if (op.endsWith("*")) { 30 v = vas.pop() * v; 31 } else if (op.endsWith("/")) { 32 v = vas.pop() / v; 33 } else if (op.endsWith("sqrt")) { 34 v = Math.sqrt(v); 35 } 36 vas.push(v); 37 } else { 38 //如果字符既非操作符也不是括号,就将它作为double值压入操作数栈 39 vas.push(Double.parseDouble(s)); 40 } 41 } 42 } 43 }
代码解析:每当算法遇到一个被括号包围并有一个运算符和两个操作数连接的表达式的时候,它都能将运算符和操作数的计算结果压如操作数栈,这样的结果就好像用这个值代替了该子表达式,因此用这个值代替子表达式的结果和原表达式相同。
在处理完最后一个右括号之后,操作数栈上只有一个值,他就是表达式的值。图解:
使用E.W.D.Dijkstra设计算法实现算数表达式求值
时间: 2024-10-29 06:57:42