用栈模拟计算器以及中缀转后缀表达式(逆波兰表达式)

后缀表达式(逆波兰表达式)运算方法

  • 从左向右读取表达式
  • 遇到数字就压入栈中
  • 遇到运算符就弹出栈顶和次顶元素。用 次顶元素 运算符 栈顶元素,并将运算结果压入栈中,直到栈为空,最终结果就是运算结果

设计

中缀表达式转后缀表达式

  • 从左向右读取中缀表达式,并且创建 栈s1队列s2(因为s2只存不取且还要考虑出栈后逆序的问题,所以这里用队列来代替栈)
  • 如果读到的元素的数字,就直接入队放入s2中
  • 如果读到的是 运算符(运算符判定)
  • 如果s1为空,则将该运算符压入s1
  • 如果s1不为空
    • 如果该运算符为 左括号,则直接压入s1
    • 如果该运算符为 右括号,则将s1中的元素依次出栈并入队到s2中, 直到遇见左括号为止(括号不放入s2中)
    • 如果该运算符的优先级 高于s1栈顶的运算符,则将该元素压入s1
    • 如果该运算符的优先级 小于等于s1栈顶的运算符,则弹出s1栈顶的元素,并将其放入s2中,该运算符重 新判定入栈操作(运算符判定步骤)
  • 如果中缀表达式已经读取完毕,则将s1中的元素依次出栈,放入s2中
  • s2中的元素依次出队,该顺序即为后缀表达式

用栈模拟计算器以及中缀转后缀表达式(逆波兰表达式)

代码

java;collapse:true;;gutter:true; import java.util.ArrayList; import java.util.List; import java.util.Stack;</p> <p>public class PoiandNotation { public static void main(String[] args) { String expression = "1+((2+3)*4)-5";//定义一个中缀表达式 List infixExpressionList = toInfixExpressionList(expression); System.out.println("中缀表达式的list="+infixExpressionList); List suffixExpreesionList = parseSuffixExpreesionList(infixExpressionList); System.out.println("后缀表达式的List="+suffixExpreesionList);</p> <pre><code> System.out.println("expression的结果为: " + calculate(suffixExpreesionList)); } /** * 将中缀表达式转化为后缀表达式(逆波兰表达式) * @param ls 传入的中缀表达式list集合 * @return */ public static List parseSuffixExpreesionList(List ls){ Stack s1 = new Stack<>();//用于暂存运算符 List s2 = new ArrayList<>();//用于存放逆波兰表达式,因为只存不取且还要考虑出栈后逆序的问题,所以这里用集合来代替栈 for (String item : ls){//循环遍历中缀表达式的每一个元素 if (item.matches("\\d+")){//多位数的情况直接入s2 s2.add(item); }else if (item.equals("(")){ s1.push(item); }else if (item.equals(")")){//碰到右括号时,s1一直出栈到s2里,直到碰到左括号为止 while (!s1.peek().equals("(")){ s2.add(s1.pop()); } s1.pop();//取出左括号 }else { while (s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)){ //当s1栈顶运算符优先级大于或等于当前扫描到的运算符优先级,则出栈放入s2 s2.add(s1.pop()); } s1.push(item);//把当前扫描到的运算符入栈到s1 } } //将s1剩余的运算符全部放入s2 while (s1.size() != 0){ s2.add(s1.pop()); } return s2; } /** * 将一个中缀表达式以集合的形式输入 * @param s 输入的中缀表达式 * @return */ public static List toInfixExpressionList(String s){ List ls = new ArrayList<>(); int i = 0;//用于扫描中缀表达式 char c;//把每一个扫描到的字符存到c里 String str;//用与拼接字符,存储多位数 do { if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57){//如果不是数字,就直接放入集合中 ls.add("" + c); i++; }else { str = "";//初始化 while (i < s.length() && (c = s.charAt(i)) >= 48 && (c = s.charAt(i)) getSuffixList){ Stack stack = new Stack<>(); for (String item : getSuffixList) { if (item.matches("\\d+")){//如果是数字就直接入栈 stack.push(item); }else { int num2 = Integer.parseInt(stack.pop()); int num1 = Integer.parseInt(stack.pop()); int res = 0; if (item.equals("+")){ res = num1 + num2; }else if (item.equals("-")){ res = num1-num2; }else if (item.equals("*")){ res = num1 * num2; }else if (item.equals("/")){ res = num1 / num2; } stack.push("" + res); } } return Integer.parseInt(stack.pop()); } </code></pre> <p>}</p> <p>//定义运算符的优先级 class Operation{ private static int ADD = 1; private static int SUB = 1; private static int MUL = 2; private static int DIV = 2;</p> <pre><code>public static int getValue(String operation){ int result = 0; switch (operation){ case "+": result = ADD; break; case "-": result = SUB; break; case "*": result = MUL; break; case "/": result = DIV; break; default: System.out.println("不存在该运算符"); break; } return result; } </code></pre> <p>}

结果

用栈模拟计算器以及中缀转后缀表达式(逆波兰表达式)

Original: https://www.cnblogs.com/wyh518/p/16750841.html
Author: 腹白
Title: 用栈模拟计算器以及中缀转后缀表达式(逆波兰表达式)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/622729/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 生成一个session id

    var genSessionId = function(length){ var str = genSessionId.characters; if ( !"0&quot…

    Java 2023年5月30日
    084
  • Spring基于注解配置AOP

    D:\Java\IdeaProjects\JavaProj\SpringHelloWorld\src\aop.xml <context:component-scan base…

    Java 2023年5月30日
    057
  • 在Ubuntu机器上使用war包安装Jenkins

    因为一些需求需要迁移之前使用的Jenkins,原来是按照官方文档使用apt方式安装的,这次搬迁后的机器由于默认不通外网(可以通过代理走外网),因此趁此机会,尝试改用war包方式安装…

    Java 2023年6月14日
    078
  • CSDN博客迁移至博客园

    CSDN博客迁移 由于早期在csdn中自定义了博客域名地址Xc_xdd,后期由于csdn由于我的id名称涉及政治敏感,未提前告知用户,且不给id修改机会。将我博客永久封禁,不可解封…

    Java 2023年6月8日
    062
  • 创建vue项目

    使用命令行创建vue项目时候要以管理员身份运行,否则可能会报错 安装element插件 在idea中导入vue项目,使用终端npm run serve 来运行vue项目 Origi…

    Java 2023年6月7日
    058
  • ElasticSearch增加索引字段

    PUT xxx_index-000009/_mapping/_doc?include_type_name=true { “properties”:{ &#8…

    Java 2023年6月13日
    068
  • springboot项目记录2用户注册功能

    七、注册-业务层 7.1规划异常 7.1.1用户在进行注册的时候,可能会产生用户名被占用的错误,抛出一个异常; RuntimeException异常,作为该异常的子类,然后再去定义…

    Java 2023年6月7日
    065
  • 放弃 Electron,拥抱 WebView2!JavaScript 快速开发独立 EXE 程序

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月16日
    068
  • sqlserver数据库还原存储过程脚本

    &#x5B58;&#x50A8;&#x8FC7;&#x7A0B;&#x5FC5;&#x987B;&#x8981;&#…

    Java 2023年6月7日
    061
  • asp.net ajax 客户端框架未能加载 sys 未定义

    一般来说与配置文件有关: 查看HTML源文件,会发现脚本有 后缀是.axd 把以上路径放IE里如果能提示下载,则说明是其他问题,如果不能提示继续往 下看。 我找了个能正常运行AJA…

    Java 2023年6月13日
    072
  • 无重复字符的最长子串

    https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ 上链接为Leeco…

    Java 2023年6月5日
    064
  • C#利用反射实现两个类的对象之间相同属性的值的复制

    http://blog.csdn.net/u013093547/article/details/53584591 今天在拷贝对象的时候,看着代码实在是有点烦,一堆一样的代码,还是找…

    Java 2023年5月30日
    061
  • Redis常用数据结构及应用场景

    1. 概述 Redis 一个开源的基于键值对(Key-Value)NoSQL 数据库。使用 ANSIC 语言编写、支持网络、基于内存但支持持久化。性能优秀,并提供多种语言的 API…

    Java 2023年6月5日
    063
  • SpringMVC&Maven进阶

    SpringMVC 3.1 了解SpringMVC 概述 SpringMVC技术与Servlet技术功能等同,均属于web层开发技术 学习路线 请求与响应 REST分割 SSM整合…

    Java 2023年6月6日
    087
  • 如何使用IDEA进行DOCKER调试

    引言在日常的开发过程中我们使用的开发环境通常与正式环境并不一致,这样就比较容易出现一些意外。于是我们通常会借助docker来让我们的开发和正式环境一致。那如何在docker中进行运…

    Java 2023年6月15日
    071
  • 一次 Nginx proxy_set_header 故障问题解析和延升

    本文会先由一个问题引入,然后再进行多种情况进行分析。 一、问题和排查步骤 ​ 我们应用程序从代码层面收到的 Header 中的 Host 的值是 upstream 的 名称。 我们…

    Java 2023年5月30日
    063
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球