含有+-*/()的表达式求值

对于表达式,有常用的几种形式:

  • 中缀表达式(Infix expression):操作符位于两个操作数中间,算术表达式的常规表示法。需要用括号和优先规则排除多义性。(这也正是编写程序的麻烦点,需要制定完整的优先规则)(A+B)*C-D/(E+F)
  • 后缀表达式(Postfix expression),逆波兰表示法,操作符位于操作数后面。这种方法使表达式求值很方便。AB+C*DEF+/- 。
  • 前缀表达式(Prefix expression):也叫波兰表示法,操作符写在操作数的前面。这种方法常用于编译器设计方面。-*+ABC/D+EF  

(在这里,不考虑前缀表示法)

 

 

为了简化问题,关注算法,本文的讨论基于以下三点:

  1. 只考虑 + - * / ( ) 这几个基本运算符。
  2. 运算数只考虑 0-9,这10个简单的数,方便从string中取出来。
  3. 输入的表达式没有语法错误。

 


 

现在先不考虑求值,先来考虑一个有趣的东西:表达式树

 (A+B)*C-D/(E+F)的表达式树

  1. 非叶子结点都是运算符,数值都在叶子结点。
  2. 在上面我忽略了一种情况:“-”   作为单目运算符的情况 (-a):可以让a作为右结点,左结点为空;  也可以让左结点为0;
  3. 从递归来看:一个子树能够得到一个值(返回值),该子树得到的值通过根结点的符号,左子树的值和右子树的值进行运算得到(递归实体);如果该结点为叶子结点,那么直接返回值就行了。(求值的递归公式
  4. 在表达式树中,不需要加括号,因为括号所表示的优先级以及被树的结构包含了。 (自底向上计算,同一层的位于同一结点下的数值才能够运算)
  5. 给出表达式树,要求表达式:先序遍历对应前缀表达式,中序遍历对应中缀表达式(需要看情况加括号),后序遍历对应后缀表达式。

 


先考虑最简单的表示法:如果给出后缀表达式,AB+C*DEF+/-

 

算法思路:

  • 给出后缀表达式S;建立一个栈,数字栈stack1。
  • 循环读入表达式的每一个单元:
    • 如果读入的字符是数字,那么入栈;
    • 如果读入的字符是符号,那么弹栈两次,后弹出来的记为n1,先弹出来的记为n2;那么结果就为n1-n2;然后将结果入栈。
  • 最后在栈中会得到最终结果。

 

因为后缀表达式不需要进行优先级规则的判断,因此,处理规则异常简单,只需要直接判断就行了。


如果给出的是中缀表达式,(A+B)*C-D/(E+F):

 

思路一:将中缀表达式转换为后缀表达式,然后....

posted @ 2019-11-03 08:49  B_luePhantom  阅读(662)  评论(0编辑  收藏  举报