利用栈解析算术表达式

在没有接触到栈这种数据结构时,一直觉得用程序计算四则表达式是件相当繁琐的事。但利用栈,问题就立刻变得容易许多。

何为解析算术表达式?

解析任何包括 + , - , * , / , () 和0到9数字组成的算术表达式,并计算其结果。

中缀表达式和后缀表达式

中缀表达式就是通常所说的算术表达式,比如(1+2)*3-4。

后缀表达式是指通过解析后,运算符在运算数之后的表达式,比如上式解析成后缀表达式就是12+3*4-。这种表达式可以直接利用栈来求解。

运算符的优先级

优先级运算符
1括号 ()
2负号 -
3乘方 **
4乘 *,除 /,求余 %
5加 +,减 -
6小于<,小于等于<=,大于>,大于等于>=
7等于==,不等于!=
8逻辑与
9逻辑或


即:一元运算符 > 二元运算符 > 多元运算符

解析过程

中缀表达式翻译成后缀表达式

  1. 从左向右依次取得数据a
  2. 如果 a 是数字,直接输出
  3. 如果 a 是运算符(含左右括号),则:
    • 如果 a =’(‘,放入堆栈。
    • 如果 a =’)’,依次输出堆栈中的运算符,直到遇到’(‘为止
    • 如果 a 不是’)’或者’(‘,那么就和栈顶位置的运算符 top 做优先级比较
      • 如果 a 优先级比 top 高,那么将 a 放入堆栈
      • 如果 a 优先级低于或者等于 top,那么输出 top,然后将 a 放入堆栈
  4. 如果表达式已经读取完成,而栈中还有运算符时,依次由顶端输出

如果我们有表达式 (A-B)*C+D-E/F,要翻译成后缀表达式,并且把后缀表达式存储在一个名叫output的字符串中,可以用下面的步骤。

  1. 读取’(‘,压入堆栈,output为空
  2. 读取A,是运算数,直接输出到output字符串,output = A
  3. 读取’-‘,此时栈里面只有一个’(‘,因此将’-‘压入栈,output = A
  4. 读取B,是运算数,直接输出到output字符串,output = AB
  5. 读取’)’,这时候依次输出栈里面的运算符’-‘,然后就是’(‘,直接弹出,output = AB-
  6. 读取’*’,是运算符,由于此时栈为空,因此直接压入栈,output = AB-
  7. 读取C,是运算数,直接输出到output字符串,output = AB-C
  8. 读取’+’,是运算符,它的优先级比’‘低,那么弹出’‘,压入’+”,output = AB-C*
  9. 读取D,是运算数,直接输出到output字符串,output = AB-C*D
  10. 读取’-‘,是运算符,和’+’的优先级一样,因此弹出’+’,然后压入’-‘,output = AB-C*D+
  11. 读取E,是运算数,直接输出到output字符串,output = AB-C*D+E
  12. 读取’/’,是运算符,比’-‘的优先级高,因此压入栈,output = AB-C*D+E
  13. 读取F,是运算数,直接输出到output字符串,output = AB-C*D+EF
  14. 原始字符串已经读取完毕,将栈里面剩余的运算符依次弹出,output = AB-C*D+EF/-

计算算术表达式

当有了后缀表达式以后,运算表达式的值就非常容易了。可以按照下面的流程来计算。

  1. 从左向右扫描表达式,一个取出一个数据data
  2. 如果 data 是操作数,就压入堆栈
  3. 如果 data 是操作符,就从堆栈中弹出此操作符需要用到的数据的个数,进行运算,然后把结果压入堆栈
  4. 如果数据处理完毕,堆栈中最后剩余的数据就是最终结果

比如我们要处理一个后缀表达式1234+*+65/-,那么具体的步骤如下:

  1. 首先1,2,3,4都是操作数,将它们都压入栈
  2. 取得’+’,为运算符,弹出数据3,4,得到结果7,然后将7压入栈
  3. 取得’*’,为运算符,弹出数据7,2,得到数据14,然后将14压入栈
  4. 取得’+’,为运算符,弹出数据14,1,得到结果15,然后将15压入栈
  5. 6,5都是数据,都压入栈
  6. 取得’/’,为运算符,弹出数据6,5,得到结果1.2,然后将1.2压入栈
  7. 取得’-‘,为运算符,弹出数据15,1.2,得到数据13.8,这就是最后的运算结果

大部分参考自 chenpeggy 的利用堆栈解析算术表达式,收获颇丰,故有此文。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值