计算器求值的常规解法是使用栈分别保存操作数和操作符,具体代码如下
// 这里是开头 // 这里是结尾
这种结构的实现可以满足一定复杂度的运算符,我们刚刚接触栈的时候都会自己实现以下这种表达式的运算方式。
本篇博客要介绍的是另外一种实现这种表达式计算的方法----使用表达式树
首先来介绍以下什么是表达式树:
表达式树是一棵树,他是对一个字符串形式的表达式的树形表示。图1是一个表达式树的例子(图片来自网络),从图片上可以看出,表达式的树形表示很容易计算结果,一棵表达式树的结果可以使用递归的方法很方便的求解出,看求解函数:
private double getValue(Node root) throws Exception{ if(root == null) throw new Exception("解析表达式出现异常"); switch(root.op){ case '+': return getValue(root.left)+getValue(root.right); case '-': return getValue(root.left)-getValue(root.right); case '*': return getValue(root.left)*getValue(root.right); case '/': return getValue(root.left)/getValue(root.right); case ' ': return root.val; default: throw new Exception("目前还不支持 "+root.op" 运算符。") } }
有上述代码可以看出,对于表达式树的求解可以说是很容易,程序容易写也容易理解。那么如何生成一棵表达式树呢?这是本篇博客的重点内容。
首先来看一下对于这个表达式,如何生成表达式树:2+3-4-1+5 这个表达式只含有+和-两种操作,程序操作流程如下:
1,读取一个数 2
2,读取一个操作符 +,将该数作为该操作符的左元素,如果读取不到退出
3,读取一个操作数 3,将该数作为该操作符的右操作数。
4,将该操作数节点作为一个数,回到2
经过以上操作,可以达到一棵表达式树:
现在我们考虑*/的情况,相比+-,*/是一种优先级更高的操作数 ::2+3*4-1+5