计算器:中缀表达式转后缀表达式
2015-02-10 20:21
330 查看
这几天想写一个Android的计算器,所以先写好中缀表达式到后缀表达式的计算。
例如:中缀表达式(8+9*10)-4/2+3
我们可以进行如下操作:
1、将每个操作符对应的两个操作数用括号括上(((8+(9*10))-(4/2))+3)
2、将操作符移到对应的括号外(((8(910*)+)(42)/)-3)+
3、去掉括号即可 8910*+42/-3+
是不是很简单,这样我们就讲一个中缀表达式转换成论文后缀表达式。
那么计算机中是怎样进行的呢?
转换的整体流程如下:
中缀表达式转后缀表达式的方法:
1.遇到操作数:直接输出(添加到后缀表达式中)
2.栈为空时,遇到运算符,直接入栈
3.遇到左括号:将其入栈
4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
6.最终将栈中的元素依次出栈,输出。
下面是我写得一个示例代码:
单元测试代码如下:
例如:中缀表达式(8+9*10)-4/2+3
我们可以进行如下操作:
1、将每个操作符对应的两个操作数用括号括上(((8+(9*10))-(4/2))+3)
2、将操作符移到对应的括号外(((8(910*)+)(42)/)-3)+
3、去掉括号即可 8910*+42/-3+
是不是很简单,这样我们就讲一个中缀表达式转换成论文后缀表达式。
那么计算机中是怎样进行的呢?
转换的整体流程如下:
中缀表达式转后缀表达式的方法:
1.遇到操作数:直接输出(添加到后缀表达式中)
2.栈为空时,遇到运算符,直接入栈
3.遇到左括号:将其入栈
4.遇到右括号:执行出栈操作,并将出栈的元素输出,直到弹出栈的是左括号,左括号不输出。
5.遇到其他运算符:加减乘除:弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈
6.最终将栈中的元素依次出栈,输出。
下面是我写得一个示例代码:
package cn.tzy.calculator; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import java.util.Queue; import java.util.Stack; /** * Created by gchx on 2015/2/9. */ public class Calculator { private Map<String, Integer> priority;//操作符优先级Map public Calculator() { initPriority(); } private void initPriority() { this.priority = new HashMap<>(); //这里的#号是操作符堆栈中的栈底元素,是为了程序方便处理而添加的 this.priority.put("#", 0); this.priority.put("+", 1); this.priority.put("-", 1); this.priority.put("*", 2); this.priority.put("/", 2); } //得到操作符的优先级 public int getPriority(String operator) { //这里括号进行特殊处理 if (operator.matches("[()]")) { return -1; } else { return priority.get(operator); } } //判断优先级高低 private boolean isPrior(String one, String another) { return getPriority(one) <= getPriority(another); } //得到栈顶元素 private <T> T getTopEle(Stack<T> stack) { if (stack == null) { return null; } else { return stack.get(stack.size() - 1); } } /** * @param expression 算数表达式 * @return * 将中缀表达式转换为后缀表达式 */ public Queue<String> toSuffix(String expression) { Queue<String> operandQueue = new LinkedList<>();//操作数队列 Stack<String> operatorStack = new Stack<>();//操作符堆栈 operatorStack.push("#"); String current = ""; String operator = ""; String number = ""; int start = 0; int end = 0; for (int i = 0; i < expression.length(); i++) { current = String.valueOf(expression.charAt(i)); // 如果是数字,末尾标记end++ if (current.matches("[\\d\\.]")) { // 如果数字是最后一个字符,直接将其入队列 if (i == expression.length() - 1) { operandQueue.add(current); } else { end++; } } else { // 如果是字符 // 如果是左括号,将其入栈 if (current.equals("(")) { operatorStack.push(current); } else { // 如果是右括号和其它运算符,先将前面的数字入队列 number = expression.substring(start, end); if (!number.isEmpty()) { operandQueue.add(number); } // 如果是右括号,执行出栈操作,并将出栈的元素入队列,直到弹出栈的是左括号,左括号直接出栈 if (current.equals(")")) { while (!getTopEle(operatorStack).equals("(")) { operandQueue.add(operatorStack.pop()); } operatorStack.pop(); } else { // 如果是其它运算符,弹出所有优先级大于或者等于该运算符的栈顶元素,然后将该运算符入栈 operator = current; while (isPrior(operator, getTopEle(operatorStack))) { operandQueue.add(operatorStack.pop()); } operatorStack.push(operator); } } // 将指向数字的首尾指针加1 start = end = i + 1; } } for (int i = operatorStack.size() - 1; i > 0; i--) { operandQueue.add(operatorStack.pop()); } return operandQueue; } /** * @param expression 算数表达式 * @return * 得到表达式的结果 */ public double getResult(String expression) { Queue<String> suffixQueue = toSuffix(expression); Stack<String> suffixStack = new Stack<String>(); String current = ""; double frontOperand; double backOperand; double value = 0; for (int i = suffixQueue.size(); i > 0; i--) { current = suffixQueue.poll(); //如果是数字,入栈 if (current.matches("^\\d+(\\.\\d+)*$")) { suffixStack.push(current); } else { backOperand = Double.valueOf(suffixStack.pop()); frontOperand = Double.valueOf(suffixStack.pop()); if (current.equals("+")) { value = frontOperand + backOperand; } else if (current.equals("-")) { value = frontOperand - backOperand; } else if (current.equals("*")) { value = frontOperand * backOperand; } else if (current.equals("/")) { try { value = frontOperand / backOperand; } catch (Exception e) { return 0; } } suffixStack.push(String.valueOf(value)); } } String result = suffixStack.get(0); return Double.valueOf(result); } }
单元测试代码如下:
package cn.tzy.calculator; import java.util.Queue; import org.junit.Assert; import org.junit.Test; public class CalculatorTest { private Calculator calculator; private String infix; public CalculatorTest() { this.calculator = new Calculator(); this.infix = "(8+9*10)-4/2+3"; } @Test public void testToSuffix() { Queue<String> suffix = calculator.toSuffix(infix); for (int i = suffix.size(); i > 0; i--) { System.out.print("(" + suffix.poll() + ")"); } } @Test public void testGetResult() { double result = calculator.getResult(infix); Assert.assertEquals(result, 99, 0); } }
相关文章推荐
- ---中缀表达式转换为后缀表达式---模拟计算器-----堆栈
- 计算器实现---中缀表达式转后缀表达式
- c++ 中缀表达式转后缀表达式 计算器
- 计算器(中缀表达式转后缀表达式)
- 逆波兰计算器--中缀表达式转后缀表达式
- 中缀表达式转后缀表达式之多项式计算器
- 逆波兰计算器与中缀表达式向后缀表达式的转化实例
- 前缀表达式、中缀表达式、后缀表达式
- 中缀表达式转后缀表达式 求值
- 逆波兰表达式-中缀转后缀(计算器)
- 利用栈将中缀表达式转化成后缀表达式
- 中缀表达式转化成后缀表达式
- 中缀表达式转成后缀表达式 后缀表达式求值
- 中缀表达式转换为后缀表达式
- 中缀表达式转换为后缀表达式
- 中缀表达式转换为前缀及后缀表达式并求值(java实现)
- 应用stack 计算表达式(中缀表达式,+ - × / ^)及计算器的实现
- 经典c程序(0031) ---中缀表达式转后缀表达式并求值
- 中缀表达式转换为后缀表达式-数据结构
- 栈的应用 - 中缀表达式转后缀表达式