手写逆波兰表达式-练习栈的使用

来源:互联网 发布:命运 定数 知乎 编辑:程序博客网 时间: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
原创粉丝点击