波兰逻辑学家的逆波兰表达式 思路

Posted 程序彤

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了波兰逻辑学家的逆波兰表达式 思路相关的知识,希望对你有一定的参考价值。

带小括号的中转后缀表达式:
1.初始化两个栈,运算符栈s1和中间结果栈s2
2.从左至右扫描中缀表达式
3.遇到数字时,将其压入s2
4.遇到运算符时,比较当前运算符与s1栈顶运算符的优先级:
①如果s1为空,或s1栈顶运算符为左括号(,则直接将此运算符入栈。
②否则,若优先级比栈顶运算符高,也将运算符压s1
③否则,将s1栈顶的运算符弹出并压入到s2中,再次从开始与s1中新的栈顶运算符相比较。
5.遇到括号时:
①如果是(,则直接压入s1.
②如果是),则依次弹出s1栈顶运算符并压入s2中直到遇到(为止。
6.重复2-5,直至结束。
7.将s1中剩余运算符弹出压入s2.

package.数组模拟栈.中缀转后缀;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

public class PolandCalculator {
    public static void main(String[] args) {
        String input = "1+(2+3*4)-3";
        List<String> list = infixToListparseSuf(input);
        List<String> suffixList = parseSuffixExpressionListparseSuf(list);
        int res = calculatePriority(suffixList);
        System.out.println(res);
    }

    public static List<String> infixToListparseSuf(String input){
        ArrayList<String> list = new ArrayList<>();
        int i = 0;
        String str = "";
        char c;
        do{
            if ((c = input.charAt(i)) < 48 || (c = input.charAt(i)) > 57) { // 如果是运算符
                list.add(""+c);
                i++;
            }else {
                str = "";
                while (i < input.length() && (c = input.charAt(i)) >= 48 && (c = input.charAt(i)) <= 57) {
                    str += c;
                    i++;
                }
                list.add(str);
            }
        }while (i<input.length());
        return list;
    }

    /**
     * 中缀转后缀
     * @param list
     * @return
     */
    public static List<String> parseSuffixExpressionListparseSuf(List<String> list) {
        Stack<String> stack = new Stack<>();
        ArrayList<String> queue = new ArrayList<>();

        for (String item : list) {
            if (item.matches("\\\\d+")) { // 凡是遍历到数字就放到list中
                queue.add(item);
            }
            if ("(".equals(item)) { // 凡是( 就压栈
                stack.push(item);
            }
            if (")".equals(item)) {
                while (!"(".equals(stack.peek())) { // 凡不是(也就是右括号就弹出栈顶运算符压入s2,直到遇到(为止。消除()括号
                    queue.add(stack.pop());
                }
                stack.pop();
            }
            if (!item.matches("\\\\d+")) {
                // 如果当前运算符小于栈顶运算符优先级
                while (stack.size() != 0 && Operation.getPriority(item) <= Operation.getPriority(stack.peek())) {
                    queue.add(stack.pop()); // 栈顶的优先级高必须先弹出去s2
                }
                stack.push(item);
            }
        }
        while (stack.size() != 0) {
            queue.add(stack.pop());
        }
        return queue;
    }

    /**
     * 计算后缀表达式最终运算结果
     * @param suffic
     * @return
     */
    public static int calculatePriority(List<String> suffic) {
        Stack<String> stack = new Stack<>();
        for (String item : suffic) {
            if (item.matches("\\\\d+")) {
                stack.push(item);
            }
            if (!item.matches("\\\\d+")) {
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                int res = 0;
                if ("+".equals(item)) {
                    res = num1 + num2;
                }
                if ("-".equals(item)) {
                    res = num1-num2;
                }
                if ("*".equals(item)) {
                    res = num1*num2;
                }
                if ("/".equals(item)) {
                    res = num1/num2;
                }
                stack.push(""+res);
            }
        }
        return Integer.parseInt(stack.pop());
    }
}

class Operation {

    public static int getPriority(String opert) {
        int level = 0;
        switch (opert) {
            case "+":
                level = 1;
                break;
            case "-":
                level = 1;
                break;
            case "*":
                level = 2;
                break;
            case "/":
                level = 2;
                break;
        }
        return level;

    }
}

以上是关于波兰逻辑学家的逆波兰表达式 思路的主要内容,如果未能解决你的问题,请参考以下文章

算法中缀表达式转成后缀表达式(逆波兰表达式)再计算得出结果

逆波兰算术表达式 C语言

C语言 逆波兰表达式 算法

数据结构与算法之深入解析“逆波兰表达式求值”的求解思路与算法示例

逆波兰表达式

递归--逆波兰表达式