package base.第一章.背包_队列_和栈.双栈之算术表达式;
import base.第一章.背包_队列_和栈.api.下压栈.Stack;
import edu.princeton.cs.algs4.StdIn;
import edu.princeton.cs.algs4.StdOut;
/**
* Created by MK on 2018/7/20.
* 使用双栈,求得算术表达式
*/
public class Evaludate {
// 循环字符串
public static Stack<Double> while_str(String str) {
//创建2个栈,一个存储运算符,一个存储操作数
Stack<String> ops = new Stack<String>(); //存储运算符
Stack<Double> vals = new Stack<Double>(); //存储操作数
for (int i = 0; i < str.length(); i++) {
char item = str.charAt(i);
String s = item + "";
if (s.equals("(")) ; //什么都不做
else if (s.equals("+")) ops.push(s); //压入到栈中
else if (s.equals("-")) ops.push(s);
else if (s.equals("*")) ops.push(s);
else if (s.equals("/")) ops.push(s);
else if (s.equals("sqrt")) ops.push(s);
else if (s.equals(")")) //在遇到右括号时,弹出一个运算符,弹出所需数量的操作数,并将运算符和操作数的运算结果压入操作数栈
{
/**
* 可这么理解:
* (1+ ( (2+3) * (4 * 5)))
* 前提:下压栈后进来的先出去
* op:当我碰到")"的时候,我要将对应的运算符弹出,对应的就是上述公式中的"2+3"中的"+",因为"1+"中的"+"是先压入栈中的
* v:其次在将操作数取出,取出的是上述中的,2+3中的3
* 最后当我等于+号的时候,再弹出操作数,此时的操作数就是2,再让其加上,上面公式中取到的3
* */
String op = ops.pop();
double v = vals.pop();
if (op.equals("+")) v = vals.pop() + v;
if (op.equals("-")) v = vals.pop() - v;
if (op.equals("*")) v = vals.pop() * v;
if (op.equals("/")) v = vals.pop() / v;
if (op.equals("sqrt")) v = Math.sqrt(v);
vals.push(v);//将计算后的值,压入到对应的栈中
} else
vals.push(Double.parseDouble(s)); //将操作数压入到栈中
}
return vals;
}
public static void main(String[] args) {
/**
* 注意有大前提
* 我算术表达式,需要以")"右括号结尾才可进行计算
* 所传数字如果是2位数的话,就有问题了
*
* */
while (!StdIn.isEmpty()) {
String s = StdIn.readLine();
Stack<Double> vals = while_str(s);
StdOut.println(vals.pop());//在处理完最后一个右括号的时候,操作数栈中只会又一个值,他就是表达式的值
}
}
}