下面题目是LeetCode算法:逆波兰表达式求值(java实现)

逆波兰表达式即后缀表达式。

题目:

 有效的运算符包括 +-*/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式、同时支持括号。(假设所有的数字均为整数,不考虑精度问题)

计算工具:

  1. /**
  2. * 计算工具
  3. * @author monkjavaer
  4. * @date 2018/9/13 14:35
  5. */
  6. public class CalculatorUtil {
  7. /**
  8. * 加
  9. */
  10. private static final String ADD = "+";
  11. /**
  12. * 减
  13. */
  14. private static final String SUBTRACT = "-";
  15. /**
  16. * 乘
  17. */
  18. private static final String MULTIPLICATION = "*";
  19. /**
  20. * 除
  21. */
  22. private static final String DIVISION = "/";
  23. /**
  24. * 左括号
  25. */
  26. private static final String LEFT_PARENTHESIS = "(";
  27. /**
  28. * 右括号
  29. */
  30. private static final String RIGHT_PARENTHESIS = ")";
  31.  
  32. /**
  33. *
  34. * 提供给外部的计算方法
  35. *
  36. * @param expression 后缀表达式
  37. * @return 计算结果
  38. */
  39. public static int calculation(Expression expression) throws Exception {
  40. List<String> list = getPostfix(expression);
  41. Stack<Integer> calculationStack = new Stack<>();
  42. Integer operandRight;
  43. Integer operandLeft;
  44. for (String item : list) {
  45. if (ADD.equals(item)) {
  46. operandRight = calculationStack.pop();
  47. operandLeft = calculationStack.pop();
  48. calculationStack.push(operandLeft + operandRight);
  49. } else if (SUBTRACT.equals(item)) {
  50. operandRight = calculationStack.pop();
  51. operandLeft = calculationStack.pop();
  52. calculationStack.push(operandLeft - operandRight);
  53. } else if (MULTIPLICATION.equals(item)) {
  54. operandRight = calculationStack.pop();
  55. operandLeft = calculationStack.pop();
  56. calculationStack.push(operandLeft * operandRight);
  57. } else if (DIVISION.equals(item)) {
  58. operandRight = calculationStack.pop();
  59. operandLeft = calculationStack.pop();
  60. calculationStack.push(operandLeft / operandRight);
  61. } else {
  62. calculationStack.push(Integer.parseInt(item));
  63. }
  64. }
  65.  
  66. return calculationStack.pop();
  67. }
  68.  
  69. /**
  70. * 判断字符为运算符(+,-,*,/)
  71. *
  72. * @param c 输入字符
  73. * @return
  74. */
  75. private static boolean isOperator(char c) {
  76.  
  77. return ADD.equals(String.valueOf(c)) || SUBTRACT.equals(String.valueOf(c)) ||
  78. MULTIPLICATION.equals(String.valueOf(c)) || DIVISION.equals(String.valueOf(c));
  79. }
  80.  
  81. /**
  82. * 返回的是运算符的优先级
  83. *
  84. * @param operator
  85. * @return
  86. */
  87. private static int priority(Operator operator) {
  88. char operatorName = operator.getOperatorName();
  89. if (ADD.equals(String.valueOf(operatorName)) || SUBTRACT.equals(String.valueOf(operatorName))) {
  90. return 1;
  91. } else if (MULTIPLICATION.equals(String.valueOf(operatorName)) || DIVISION.equals(String.valueOf(operatorName))) {
  92. return 2;
  93. } else {
  94. return 0;
  95. }
  96. }
  97.  
  98. /**
  99. * 通过表达式获得后缀表达式
  100. *
  101. * @param expression
  102. * @return
  103. */
  104. private static List<String> getPostfix(Expression expression) throws Exception {
  105. /**
  106. * 操作符栈
  107. */
  108. Stack<Operator> operatorStack = new Stack<>();
  109.  
  110. /**
  111. * 存放后缀表达式
  112. */
  113. List<String> operandList = new ArrayList<>();
  114.  
  115. String expressionStr = expression.getExpressionStr();
  116. for (int i = 0; i < expressionStr.length(); i++) {
  117. char oneChar = expressionStr.charAt(i);
  118.  
  119. Operator operator = new Operator();
  120. operator.setOperatorName(oneChar);
  121.  
  122. //遇到操作数:直接输出(添加到后缀表达式中)
  123. if (Character.isDigit(oneChar)) {
  124. int num = oneChar - '0';
  125. while (i + 1 < expressionStr.length() && Character.isDigit(expressionStr.charAt(i + 1))) {
  126. num = num * 10 + expressionStr.charAt(i + 1) - '0';
  127. i++;
  128. }
  129. operandList.add(String.valueOf(num));
  130. } else if (LEFT_PARENTHESIS.equals(String.valueOf(oneChar))) {
  131. //遇到左括号:将其入栈
  132. operatorStack.push(operator);
  133. } else if (RIGHT_PARENTHESIS.equals(String.valueOf(oneChar))) {
  134. //遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
  135. while (!LEFT_PARENTHESIS.equals(String.valueOf(operatorStack.peek().getOperatorName()))) {
  136. operandList.add(String.valueOf(operatorStack.pop().getOperatorName()));
  137. }
  138. //然后弹出左括号
  139. operatorStack.pop();
  140. } else if (isOperator(oneChar)) {
  141. //遇到运算符
  142. //栈为空时,直接入栈
  143. if (operatorStack.isEmpty()) {
  144. operatorStack.push(operator);
  145. } else {
  146. // 如果读入的操作符为非")"且优先级比栈顶元素的优先级高或一样
  147. if (priority(operatorStack.peek()) < priority(operator)) {
  148. operatorStack.push(operator);
  149. } else if (priority(operatorStack.peek()) >= priority(operator)) {
  150. operandList.add(String.valueOf(operatorStack.pop().getOperatorName()));
  151. operatorStack.push(operator);
  152. }
  153. }
  154. }
  155. }
  156.  
  157. //最终将栈中的元素依次出栈。
  158. while (!operatorStack.isEmpty()) {
  159. operandList.add(String.valueOf(operatorStack.pop().getOperatorName()));
  160. }
  161. System.out.println(operandList);
  162. return operandList;
  163. }
  164.  
  165. }

  

  1. 表达式:
  1. /**
  2. * 表达式
  3. *
  4. * @author monkjavaer
  5. * @date 2018/9/12 19:42
  6. */
  7. public class Expression {
  8.  
  9. /**
  10. * 表达式名字
  11. */
  12. private String name;
  13.  
  14. /**
  15. * 表达式
  16. */
  17. private String expressionStr;
  18.  
  19. /**
  20. * 表达式值
  21. */
  22. private int value;
  23.  
  24. public String getName() {
  25. return name;
  26. }
  27.  
  28. public void setName(String name) {
  29. this.name = name;
  30. }
  31.  
  32. public String getExpressionStr() {
  33. return expressionStr;
  34. }
  35.  
  36. public void setExpressionStr(String expressionStr) {
  37. this.expressionStr = expressionStr;
  38. }
  39.  
  40. public int getValue() {
  41. return value;
  42. }
  43.  
  44. public void setValue(int value) {
  45. this.value = value;
  46. }
  47.  
  48. }

  

  1. 操作数:
  1. /**
  2. * 操作数
  3. * @author monkjavaer
  4. * @date 2018/9/12 19:43
  5. */
  6. public class Operand {
  7. /**
  8. * 操作数值
  9. */
  10. private Integer operandValue;
  11.  
  12. public Integer getOperandValue() {
  13. return operandValue;
  14. }
  15.  
  16. public void setOperandValue(Integer operandValue) {
  17. this.operandValue = operandValue;
  18. }
  19. }

  

  1. 运算符:
  1. /**
  2. * 运算符
  3. *
  4. * @author monkjavaer
  5. * @date 2018/9/12 19:43
  6. */
  7. public class Operator {
  8. /**
  9. * 运算符符号
  10. */
  11. private char operatorName;
  12.  
  13. public char getOperatorName() {
  14. return operatorName;
  15. }
  16.  
  17. public void setOperatorName(char operatorName) {
  18. this.operatorName = operatorName;
  19. }
  20.  
  21. }

  测试:

  1. /**
  2. * @author monkjavaer
  3. * @date 2018/9/13 11:49
  4. */
  5. public class Test {
  6.  
  7. public static void main(String[] args) {
  8. Expression expression = new Expression();
  9. expression.setExpressionStr("4 +(13 - 5)");
  10. try {
  11. System.out.println(CalculatorUtil.calculation(expression));
  12. } catch (Exception e) {
  13. e.printStackTrace();
  14. }
  15. }
  16.  
  17. }

  

  1.  

leetcode算法学习----逆波兰表达式求值(后缀表达式)的更多相关文章

  1. NYOJ 35 表达式求值(逆波兰式求值)

    http://acm.nyist.net/JudgeOnline/problemset.php?typeid=4 NYOJ 35 表达式求值(逆波兰式求值) 逆波兰式式也称后缀表达式. 一般的表达式求 ...

  2. 中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(python版本)

    定义: 中缀表达式: 在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表达式 后缀表达式: 又叫逆波兰表达式 ,不包含括号,运算符放在两个运算对象的后面,所有的计算 ...

  3. TOJ1302: 简单计算器 && TOJ 4873: 表达式求值&&TOJ3231: 表达式求值

    这些都是应用Python的eval函数的一些题目! TOJ1302传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=show ...

  4. C++基础算法学习——逆波兰表达式问题

    例题:逆波兰表达式逆波兰表达式是一种把运算符前置的算术表达式,例如普通的表达式2 + 3的逆波兰表示法为+ 2 3.逆波兰表达式的优点是运算符之间不必有优先级关系,也不必用括号改变运算次序,例如(2 ...

  5. ACM-ICPC 2018 沈阳赛区网络预赛 B Call of Accepted(表达式求值)

    题目链接:https://nanti.jisuanke.com/t/31443 相关前置链接 https://www.cnblogs.com/dolphin0520/p/3708602.html ht ...

  6. 【足迹C++primer】表达式求值

    表达式求值 /** * 功能:表达式求值(0到9) * 时间:2014年6月15日08:02:31 * 作者:cutter_point */ #include<stdlib.h> #inc ...

  7. java实现算术表达式求值

    需要根据配置的表达式(例如:5+12*(3+5)/7.0)计算出相应的结果,因此使用java中的栈利用后缀表达式的方式实现该工具类. 后缀表达式就是将操作符放在操作数的后面展示的方式,例如:3+2 后 ...

  8. LeetCode 150. 逆波兰表达式求值(Evaluate Reverse Polish Notation) 24

    150. 逆波兰表达式求值 150. Evaluate Reverse Polish Notation 题目描述 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, /.每个运算对象 ...

  9. LeetCode:逆波兰表达式求值【150】

    LeetCode:逆波兰表达式求值[150] 题目描述 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除 ...

随机推荐

  1. C. Coin Troubles 有依赖的背包 + 完全背包变形

    http://codeforces.com/problemset/problem/283/C 一开始的时候,看着样例不懂,为什么5 * a1 + a3不行呢?也是17啊 原来是,题目要求硬币数目a3 ...

  2. HTML5 WEB Storage - localStorage存储位置在哪

    localStorage作为客户端浏览器持久化存储方案 这个是浏览器隔离的,每个浏览器都会把localStorage存储在自己的UserData中,如chrome一般就是 C:\Users\你的计算机 ...

  3. FormsAuthentication权限管理

    通常我们在做访问权限管理的时候会把用户正确登录后的基本信息保存在Session中然后用户每次请求页面或接口数据的时候代上会话状态即能拿到Session中存储的基本信息Session的原理,也就是在服务 ...

  4. centos源码编译安装nginx过程记录

    前言:Centos系统编译安装LNMP环境是每来一台新服务器或换电脑都需要做的事情.这里仅做一个记录.给初学者一个参考! 一.安装前的环境 这里用的是centos 7系统. 我们默认把下载的软件放在 ...

  5. Javascript中的那些bug

    1. x(比如document) is not defined 不止要检查是不是没有声明变量就使用了,还要检查是不是对象的方法调用写错了!比如: alert( document.getElementB ...

  6. 用DataReader 分页与几种传统的分页方法的比较

    对于数据库的分页,目前比较传统的方法是采用分页存储过程,其实用 DataReader 也可以实现分页,不需要写存储过程,实现效率上也比几种比较流行的分页方法要略快. 在开始这个方法之前,让我们先创建一 ...

  7. handlesocket.md

    [介绍](http://www.uml.org.cn/sjjm/201211093.asp ) * 查看启动参数     `service mariadb status > st.txt`   ...

  8. python学习笔记(6)——for...in &while

    for x in ...循环就是把每个元素代入变量x,然后执行缩进块的语句. 注意:python中的格式也起到语法规则的作用,缩进块就是一个例 求和问题,比较异同 1/sum= ,,,,,,,,,]: ...

  9. HDU_1232_畅通工程

    Problem Description 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道 ...

  10. 梦想CAD控件网页版扩展数据

    随着基于CAD的应用软件飞速发展,经常需要保存一些与图形可视性无关的数据,即非图形参数.例如在绘制化验样图中包含品位数据.MxCAD定义一类新的参数——实体扩展数据.扩展数据与实体的可视性无关,而是用 ...