zoukankan      html  css  js  c++  java
  • 利用栈实现表达式求值

    前言

    假如要你实现一个可以识别表达式的简易计算器,你会怎么实现?例如用户输入:

    3 + 5 * (2 - 4)

    可以直接得出计算结果:-7。对于人类来说,我们很容易计算出来,因为我们从左往右看,看到后面括号时,知道括号内的计算优先级最高,因此可以先计算括号内的,然后反过来计算乘法,最后计算加法,得到最终结果。

    后缀表达式

    而对于计算机来说,实际也可以采用类似的顺序,先记录存储3为a,然后存储5为b,计算2-4结果存入c,再然后计算b*c存储d,最终计算a+d得到最终结果。而这种计算过程的操作顺序可描述如下(把操作符号放在操作数后面):

    3 5 2 4 - * +

    这种记法叫做后缀或逆波兰记法(而我们平常见到的叫中缀记法),它的特点是不需要用括号就能表示出整个表达式哪部分运算先进行,也就是说不需要考虑优先级,这非常符合计算机的处理方式。这种记法很容易使用我们前面介绍的栈来求值,但是前提是需要将中缀表达式先转换为后缀表达式。对于这种转换,我们也可以使用前面介绍的栈-C语言实现或者将要介绍的树来完成,因篇幅有限,本文不准备介绍。

    接下来将会介绍如何利用中缀表达式进行求值。

    利用栈实现中缀表达式求值

    前面也说到,所谓中缀表达式,就是我们能看到的正常表达式,中缀表达式求值,也就是直接对输入的表达式进行求值。为简单起见,我们这里假设只涉及加减乘除和小括号,并且操作数都是正整数,不涉及更加复杂的数据或运算。

    计算思路:

    • 使用两个栈,stack0用于存储操作数,stack1用于存储操作符
    • 从左往右扫描,遇到操作数入栈stack0
    • 遇到操作符时,如果优先级低于或等于栈顶操作符优先级,则从stack0弹出两个元素进行计算,并压入stack0,继续与栈顶操作符的比较优先级
    • 如果遇到操作符高于栈顶操作符优先级,则直接入栈stack1
    • 遇到左括号,直接入栈stack1,遇到右括号,则直接出栈并计算,直到遇到左括号

    上面的思路可能看起来不是很明确,我们举一个简单的例子,假如要对下面的表达式求值:

    * (2 + 3 )* 8 + 5

    我们从左往右开始扫描。首先遇到操作数‘6’,和操作符‘*’,分别入栈
    stack0:

    栈顶    
    6        

    stack1:

    栈顶    
    *        

    继续往后扫描,遇到‘(’直接入栈,‘2’入栈,栈顶是左括号,’+‘入栈,‘3’入栈
    stack0:

      栈顶  
    6 2 3    

    stack1:

      栈顶  
    * ( +    

    继续往后扫描,遇到右括号,它与栈顶操作符‘+’相比,优先级要高,因此,将‘+’出栈,弹出两个操作数‘3’,‘2’,计算结果得到‘5’,并入栈:

    stack0:

     栈顶   
    6 5      

    stack1:

     栈顶   
    * (      

    继续出栈,直到遇到左括号
    stack0:

     栈顶   
    6 5      

    stack1:

    栈顶    
    *        

    继续往后扫描,遇到操作符‘’,优先级与栈顶‘’优先级相同,因此弹出操作数并计算得到30入栈,最后‘*’入栈

    stack0:

    栈顶    
    30        

    stack1:

    栈顶    
    *        

    继续扫描,‘8’入栈,操作符‘+’优先级小于‘*’,弹出操作数计算得到结果‘240’,并将其入栈,最后‘+’也入栈

    stack0:

    栈顶    
    240        

    stack1:

    栈顶    
    +        

    最后‘5’入栈,发现操作符栈不为空,弹出操作符‘+’和两个操作数,并进行计算,得到‘245’,入栈,得到最终结果。
    stack0

    栈顶    
    245        

    stack1:

         
             

    代码实现

    完整代码实现请访问利用栈实现表达式求值

    总结

    本文介绍了利用栈对中缀表达式进行求值,而代码实现还有很多不足之处,例如对表达式的正确性校验不足,只能处理正整数等等,欢迎在此基础上完善补充。尽管如此,整个过程对使用栈进行中缀表达式的求值做了一个较为完整的介绍,因此具有一定的参考性。

    微信公众号【编程珠玑】:专注但不限于分享计算机编程基础,Linux,C语言,C++,数据结构与算法,工具,资源等编程相关[原创]技术文章,号内包含大量经典电子书和视频学习资源。欢迎一起交流学习,一起修炼计算机“内功”,知其然,更知其所以然。

    公众号编程珠玑公众号编程珠玑
  • 相关阅读:
    Linux基础命令---arch
    JSON漫谈
    django中外键关联表的查询随笔
    <django中render_to_response的可选参数和使用方法>
    有趣的Redis:缓存被我写满了,该怎么办?
    2020全球C++及系统软件技术大会成功落下帷幕
    AWS 宣布创建 Elasticsearch 和 Kibana 分支
    Flutter开发指南之理论篇:Dart语法05(单线程模型,事件循环模型,Isolate)
    自定义注解!绝对是程序员装逼的利器!!
    Java8 Stream
  • 原文地址:https://www.cnblogs.com/bianchengzhuji/p/10679924.html
Copyright © 2011-2022 走看看