前言
前中后缀表达式的基本介绍可见上篇文章:前中转后缀,本文不再赘述。
本文将实现将中缀、后缀表达式转变为前缀表达式并且实现一个简单的前缀表达式计算器。同时本文依旧约定表达式的基本数据结构如下:
1 | enum OperType |
注:本文所指表达式操作符只含有双目运算符且运算符的结合顺序为从左到右。
中缀转前缀表达式
前缀表达式在表达式树中的遍历顺序为:根->左->右,而后缀表达式的遍历顺序为:左->右->根。如果把后缀表达式逆序(即采用栈来存放结果),此时得到的表达式操作数和结合顺序均发生反向,如果我们采用从中缀表达式右端向左端扫描的方式则可以抵消这个影响。中缀表达式转后缀表达式中有一个经典的调度场算法,我们综合上述考虑和修改该算法便可以得到中缀转前缀表达式的算法。算法对于括号处理也需要反向。同时在操作符压栈时和中缀转后缀略有区别的是如果优先级相等也需要接着入栈(左结合)。具体实现代码如下:
1 |
|
中缀转前缀代码测试
使用如下图所示表达式树生成的中缀表达式来进行测试:图片来源
1 |
|
后缀转前缀表达式
前缀和后缀表达式在表达式树中的遍历顺序:前缀,根->左->右;后缀,左->右->根。分析和前缀转中缀类似,但是考虑后缀顺序反向,因此我们采取从后往前扫描的策略,同时采用栈存放操作数操作符以及根访问次数。只需将前缀转后缀代码稍加修改即可,具体代码如下所示:
1 |
|
后缀转前缀代码测试
1 |
|
前缀表达式求值
前缀表达式可以快速转变成后缀表达式然后通过后缀表达式间接进行求值,但是前缀表达式也是可以直接求值,前缀表达式正确地表达了运算优先顺序,后缀表达式是从前往后依次求值,那么考虑到前缀表达式操作符在运算符前面,因此我们只需从后往前扫描前缀表达式即可,其余部分和后缀表达式求值类似,其代码稍作修改既可用于前缀求值,具体代码如下:
1 |
|
后缀表达式求值代码测试
在进行测试时直接使用上节求出的后缀表达式,具体代码如下:
1 |
|