逆波兰表达式(后缀表达式)
来源:互联网 发布:51单片机助手 编辑:程序博客网 时间:2024/06/06 16:47
逆波兰式,也叫做后缀表达式,每一运算符都置于其运算对象之后,故称为后缀表示。值得注意的是,后缀表达式没有优先级的概念,会按照运算符从左向右进行运算。这种理解这对于把普通表达式转换为后缀表达式很重要。比如下面的式子:
a+b ---> a,b,+
a+(b-c) ---> a,b,c,-,+
a+(b-c)*d ---> a,b,c,-,d,*,+
a+d*(b-c)--->a,d,b,c,-,*,+
a=1+3 ---> a=1,3 +
实现代码如下:
/** * 计算后缀表达式,操作很简单,就是入栈和出栈进行计算 * @param tokens 后缀表达式 */public static int evalRPN(String[] tokens) {int returnValue = 0;String operators = "+-*/";Stack<String> stack = new Stack<String>();for (String t : tokens) {//如果解析到的字符不是运算符就将当前的值push到栈里,if (!operators.contains(t)) {//push~stack.push(t);} else {//如果解析到的是运算符,那么就可以进行计算了//能够保证计算结果的正确性的前提是有两个保证://1、后缀表达式的特性:运算符是紧跟着操作数后面的//2、栈的特点:栈是先进后出的特点,先push进去的元素,在pop出一个元素时,取出的是最后push进去的元素,注意,pop出一个元素后,该元素就不存在栈中了//基于以上两点,可以形成基本思路:对后缀表达式进行遍历,如果遇到的不是运算符那么就push到栈中,如果遇到运算符就将前面的两个数字取出运算//由此可见,如果一个表达式的第一个运算符的前面只有一个数字,这样的表达式不应该算是后缀表达式int a = 0, b = 0;if (!stack.empty()) {a = Integer.valueOf(stack.pop());}if (!stack.empty()) {b = Integer.valueOf(stack.pop());}//当前解析到的运算符,本例中的运算符是用一个字符串表示的四种基本运算int index = operators.indexOf(t);//将计算后的值再次push到栈中switch (index) {case 0:stack.push(String.valueOf(a + b));break;case 1:stack.push(String.valueOf(b - a));break;case 2:stack.push(String.valueOf(a * b));break;case 3:stack.push(String.valueOf(b / a));break;}}}//栈顶上的元素就是累计算的结果returnValue = Integer.valueOf(stack.pop());return returnValue;}
以上算法是摘自:http://www.programcreek.com/2012/12/leetcode-evaluate-reverse-polish-notation/ 我只加了两个if判断。
后缀表达式,运算及其简洁,只需要通过入栈和出栈就可以完成简单运算,但是我们平时使用的都是普通表达式,因此下面来实现将普通表达式转换为后缀表达式的算法:
/** * 优先级比较 * @param operator1 比较值 * @param operator2 被比较值 * @return 小于等于返回false,大于返回true */ public static boolean comparePrior(String operator1, String operator2) { if("(".equals(operator2)) { return true; } if ("*".equals(operator1) || "/".equals(operator1)) { if ("+".equals(operator2) || "-".equals(operator2)) { return true; } } return false; } /** * 转为后缀表达式: * 1、如果是"("直接压入stack栈。 * 2、如果是")",依次从stack栈弹出运算符加到数组newExpressionStrs的末尾,值到遇到"("; * 3、如果是非括号,比较扫描到的运算符,和stack栈顶的运算符。如果扫描到的运算符优先级高于栈顶运算符则, * 把运算符压入栈。否则的话,就依次把栈中运算符弹出加到数组newExpressionStrs的末尾,直到遇到优先级低于扫描到的运算符或栈空, * 并且把扫描到的运算符压入栈中。就这样依次扫描,知道结束为止。如果扫描结束,栈中还有元素,则依次弹出加到数组newExpressionStrs的末尾, * 就得到了后缀表达式。 * @param expressionStrs * @return */ public static String[] toSuffixExpression(String[] expressionStrs) { //新组成的表达式 List<String> newExpressionStrs = new ArrayList<String>(); Stack<String> stack = new Stack<String>(); for (int i = 0; i < expressionStrs.length; i++) { // 如果是左括号,则直接 if ("(".equals(expressionStrs[i])) { stack.push(expressionStrs[i]); } else if ("+".equals(expressionStrs[i]) || "-".equals(expressionStrs[i]) || "*".equals(expressionStrs[i]) || "/".equals(expressionStrs[i])) { if (!stack.empty()) { String s = stack.pop(); //如果栈值优先级小于要入栈的值,则继续压入栈 if(comparePrior(expressionStrs[i], s)) { stack.push(s); } else { //否则取出值 newExpressionStrs.add(s); } } stack.push(expressionStrs[i]); } else if (")".equals(expressionStrs[i])) { //如果是")",则出栈,一直到遇到"(" while (!stack.empty()) { String s = stack.pop(); if (!"(".equals(s)) { newExpressionStrs.add(s); } else { break; } } } else { newExpressionStrs.add(expressionStrs[i]); } } while (!stack.empty()) { String s = stack.pop(); newExpressionStrs.add(s); } return newExpressionStrs.toArray(new String[0]); }
1 0
- 逆波兰表达式(后缀表达式)2
- 逆波兰表达式(后缀表达式)
- 后缀表达式(逆波兰表达式)
- 逆波兰-后缀表达式
- 逆波兰表达式,后缀表达式
- 中缀表达式转后缀表达式(逆波兰表达式)
- 数据结构--中缀表达式转为后缀表达式(逆波兰表达式)
- 中缀表达式转后缀表达式(逆波兰表达式)
- 逆波兰表达式 中缀表达式 后缀表达式
- 逆波兰式(后缀表达式)
- java 逆波兰表达式 (后缀表达式) 计算器
- 逆波兰式(中缀表达式转成后缀表达式)
- 逆波兰表达式(后缀表达式)及其计算
- 利用顺序栈计算后缀表达式(逆波兰表达式)
- 中缀表达式转后缀表达式(逆波兰式)
- 表达式求值(逆波兰式后缀表达式)
- 逆波兰表达式(后缀表达式的求解)
- 【数据结构】中缀表达式转换后缀表达式(逆波兰式)
- 从Eclipse转移到IntelliJ IDEA一点心得
- 自己测试apache绑定域名
- 汇编语言学习笔记 第一节:寄存器
- iOS 解决无法使用Quartz2D绘制1像素直线的问题
- 令病菌的力减弱长期吃药反而会产生抗药性
- 逆波兰表达式(后缀表达式)
- 面试
- 漫游Kafka入门篇之简单介绍
- activeMQ--Failover Transport
- Jfinal---备忘(1)
- 准备动手写一个博客网站了
- 全面解析C#中静态与非静态
- oracle-扫盲贴:存储过程实现增删改查
- 温故而知新,可以为师矣