手写逆波兰表达式-练习栈的使用
来源:互联网 发布:命运 定数 知乎 编辑:程序博客网 时间:2024/05/31 06:21
概念:
逆波兰表达式也叫后缀表示法,即操作符号都置于操作数的后面,逆波兰表达式可以不用括号来标识操作符的优先级。例如:3+4 是一个中缀表达式,转换成逆波兰表达式为34+ 。有人可能会想有后缀表达式,中缀表达式,那有没有前缀表达式呢?答案是:有前缀表达式,也叫波兰表达式,上文中的3+4 用前缀表达式表示为+34。
用途:
了解了什么是逆波兰表达式,那它有什么具体的用途呢?
1.逆波兰表达式中不需要括号,用户只需按照表达式顺序求值,让堆栈自动记录中间结果;同样的,也不需要指定操作符的优先级
2.机器状态永远是一个堆栈状态,堆栈里是需要运算的操作数,栈内不会有操作符。
3.当有操作符时就计算,因此,表达式并不是从右至左整体计算而是每次由中心向外计算一部分,这样在复杂运算中就很少导致操作符错误。
计算原理:
逆波兰表达式进行数据计算的时候一般分为两步:
1.将中缀表达式转换为后缀表达式
2.对转换完成后的后缀表达式进行计算
package com.jason.datastruct;import java.util.ArrayList;import java.util.List;import java.util.Stack;import java.util.StringTokenizer;public class ReversePolish { private List<String> sList = new ArrayList<String>();// 中缀表达式集合 private List<String> dList = new ArrayList<String>();// 后缀表达式集合 private Stack<String> opStack = new Stack<String>();// 操作符栈 private Stack<String> rStack = new Stack<String>();// 结果运算栈 private final int level1 = 0;// +-的级别是0 private final int level2 = 1;// */的级别是1 private final int level3 = 3;// 左右括号是3 // 初始化 public ReversePolish(String input) { // a+b-c*(d+e) 转换为实际值例如:1+2-3*(4+5) StringTokenizer st = new StringTokenizer(input, "+-*/()", true); while (st.hasMoreTokens()) { sList.add(st.nextToken()); } } public List<String> infix2ReversePolish() { for (String string : sList) { // 如果是数字 直接放入dlist 数组 if (isNumber(string)) { dList.add(string); } else if (isOperation(string)) { // 如果是运算符 放入运算符栈 opHandler(string); } else { System.out.println("非法操作符"); } } // 将栈置空 while (!opStack.empty()) { dList.add(opStack.pop()); } return dList; } private void opHandler(String s) { for (Object string : opStack.toArray()) { System.out.print(string + ""); } System.out.println(); // 如果运算符栈是空 直接放入栈 if (opStack.empty()) { opStack.push(s); return; } // 如果是(直接入栈 if (s.equals("(")) { opStack.push(s); return; } // 如果是) 将(和)之间的出栈 if (s.equals(")")) { while (!"(".equals(opStack.peek())) { dList.add(opStack.pop()); } opStack.pop(); // String tmp = ""; // while (!"(".equals(tmp = opStack.pop())) { // dList.add(tmp); // } return; } // 如果栈顶是( 直接入栈 if ("(".equals(opStack.peek())) { opStack.push(s); return; } // 如果运算符等级大于当前预算符 直接入栈 if (comparePriority(s, opStack.peek())) { opStack.push(s); return; } // 如果等级小 或者等于 栈里的出栈 // 小的入栈 (在调用一次) if (!comparePriority(s, opStack.peek())) { dList.add(opStack.pop()); opHandler(s); } } // 判斷是否是数字 private boolean isNumber(String s) { return s.matches("\\d+"); } // 判断是否是运算符 private boolean isOperation(String s) { return s.matches("[\\+\\-\\*\\/\\(\\)]"); } // 判断op1 的优先级 是否大于 op2的优先级 private boolean comparePriority(String op1, String op2) { return getLevel(op1) > getLevel(op2); } // 获得操作符的优先级 private int getLevel(String op) { if ("+".equals(op) || "-".equals(op)) { return level1; } if ("*".equals(op) || "/".equals(op)) { return level2; } if ("(".equals(op) || ")".equals(op)) { return level3; } return -1; } // 计算 反波兰表达式 public String resultFromReversePolish() { for (String string : dList) { // 如果是数字 入栈 if (isNumber(string)) { rStack.push(string); } else if (isOperation(string)) { // 如果是运算符 取出上面2个 进行运算 结果入栈 if (string.equals("(") || string.equals(")")) { return "公式错误"; } int num2 = Integer.parseInt(rStack.pop()); int num1 = Integer.parseInt(rStack.pop()); String result = operation(num1, string, num2); rStack.push(result); } } if (rStack.empty()) { return ""; } return rStack.pop(); } //运算 private String operation(int num1, String string, int num2) { switch (string) { case "+": return num1 + num2 + ""; case "-": return num1 - num2 + ""; case "*": return num1 * num2 + ""; case "/": return num1 / num2 + ""; default: return ""; } }}
测试类:
package com.jason.datastruct;import java.util.ArrayList;public class ReversePolishTest { public static void main(String[] args) { String str="1+((2-3)*(4+5))+((6/2))"; System.out.println("中缀表达式:"+str); ReversePolish rPolish=new ReversePolish(str); ArrayList<String> reversePolish =(ArrayList<String>) rPolish.infix2ReversePolish(); System.out.println("转换 逆波兰表达式:"); for (String string : reversePolish) { System.out.print(string+","); } //1,2,3,4,-,*,6,*,+,7,-, System.out.println(); System.out.println("结果\t:"+rPolish.resultFromReversePolish()); }}
结果:
中缀表达式:1+((2-3)*(4+5))+((6/2))++(+((+((-+(+(*+(*(+(*(++(*+++(+((+((/+(转换 逆波兰表达式:1,2,3,-,4,5,+,*,+,6,2,/,+,结果 :-5
阅读全文
0 0
- 手写逆波兰表达式-练习栈的使用
- Stack类的使用:逆波兰表达式
- 栈 逆波兰表达式
- Python小练习:逆波兰表达式计算
- 波兰、逆波兰表达式
- 数据结构 栈的应用 逆波兰表达式
- 栈的应用:逆波兰表达式
- 栈的应用—逆波兰表达式
- 栈的应用:逆波兰表达式求值
- 栈的应用--逆波兰表达式
- 使用栈解决逆波兰表达式(后缀表达式)
- 逆波兰表达式的求解
- 逆波兰表达式的生成
- 波兰表达式和逆波兰表达式(栈)
- 数据结构6:使用栈计算逆波兰表达式
- java使用栈和逆波兰表达式实现四则运算
- 栈应用之使用逆波兰输入求表达式的值
- 栈的表达式与波兰表达式
- Discretized Continuous Speech Emotion Recognition with Multi-Task Deep Recurrent Neural Network
- 时间日期操作组件joda 简单体验
- python圣斗士修炼(十三):错误和异常处理
- C语言之旅(6)内存空间的管理
- 【Web】(AJAX缓存问题)挂载Flask上,更改本地文件,ajax依然读取以前的文件
- 手写逆波兰表达式-练习栈的使用
- 朴素贝叶斯文本分类算法学习
- Android Tools 属性介绍
- 二叉树的非递归实现前中后序遍历
- 编程生涯的一点感想1
- 改变MFC按钮的颜色和字体大小的处理
- 有趣的CSS-- 单行居中,两行居左,超过两行省略
- 移动安全大讲堂第一讲:移动应用现状分析(内附注册抽奖中奖名单)
- 程序人生--为什么我总赶不上好时候?