Among the data structures and algorithms turn postfix infix expression and RPN Calculator

Among the data structures and algorithms turn postfix infix expression and RPN Calculator


table of Contents

  1. Postfix infix expression turn ideas analysis
  2. Enter the suffix thinking analysis results
  3. Overall code implementation

1. postfix infix expression turn ideas analysis

Postfix expression computing equation for computing, but people are not easy to write, especially in the expression very long, so in development, we need to turn infix expression into postfix notation.

(A) the following steps

  1. Initialization two stacks: stack operators s1 and s2 stack store intermediate results;

  2. Conjugated expression from left to right scan;

  3. Operand is encountered, the press-S2;

  4. Encountered operator, compares it to the stack s1 operator precedence:

    1. If sl is empty, or top of the stack to the left of the operator bracket "(", this operator directly push;
    2. Otherwise, if the operator stack higher priority than the operator, the operator will also be pressed into the SL;
    3. Otherwise, the pop-up operator stack sl and s2 into the press, go to (1 a 4) sl again compared to the new top of stack operator;
  5. Encountered parentheses:

    1. If it is left bracket "(" directly pressed into s1
    2. If a right parenthesis ")", then in turn the pop-up operator stack s1, and pressed into s2, until it left parenthesis is encountered, then discards the pair of brackets
  6. Repeat steps 2-5 until the rightmost expression

  7. The remaining operators sl sequentially press-pop and s2

  8. In the pop-up element s2 sequentially and outputs, namely reverse infix expressions corresponding postfix expression results

(B) illustrates
the infix "1 + ((2 + 3 ) × 4) -5" postfix expression is converted to the following process
so the result is: "123 + 4 × + 5- "

Here Insert Picture Description


2. Enter the suffix thinking analysis results

We completed a reverse Polish calculator, required to complete the following tasks:

  1. Enter a reverse Polish notation (postfix notation), using the stack (Stack), the calculation result
  2. Because here we are mainly talking about data structures, thus simplifying the calculator only supports integer calculations.
  3. Analysis of ideas:

For example: (3 + 4) × 5.6 corresponding postfix expression is 34 + 5 × 6. For postfix expression following steps:

  1. Scan from left to right, 3 and 4 will be pushed onto the stack;
  2. We met + operator, and thus the pop-up 4 3 (the top element 4, the top element 3 times), the calculated value of 4 + 3, 7 too, and then the stack 7;
  3. The 5 stack;
  4. Followed × operator, and thus the pop-up 7 5, 7 × 5 = calculated 35, the stack 35;
  5. The 6 stack;
  6. Finally. Operator, the calculated value of 35.6, i.e. 29, it follows that the final result

3. The overall code implementation

package com.stack;

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

public class PolandNotation {
    public static void main(String[] args) {
        /**
         * 完成一个将中缀表达式转成后缀表达式的功能
         * 说明
         * 1. 1+((2+3)*4)-5 => 1 2 3 + 4 * + 5 -
         * 2. 因为直接对str进行操作不方便,因此先将“1+((2+3)*4)-5” =》 中缀表达式对应的List
         *      即“1+((2+3)*4)-5” =》 ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]
         * 3. 将得到的中缀表达式的list =》 后缀表达式对应的List
         *      [1, +, (, (, 20, +, 3, ), x, 4, ), -, 5] =》 ArrayList[1,2,3,+,4,*,+,5,-]
         */
        String expression = "1+((2+3)*4)-5";
        List<String> infixExpressionList = toInfixExpressionList(expression);
        System.out.println("中缀表达式的List="+infixExpressionList);
        List<String> suffixExpressionList = parseSuffixExpressionList(infixExpressionList);
        System.out.println("后缀表达式对应的List:"+suffixExpressionList);

        System.out.println("expression="+calculate(suffixExpressionList));

    }

    //方法:将得到的中缀表达式的list =》 后缀表达式对应的List
    public static List<String> parseSuffixExpressionList(List<String> ls) {
        //初始化栈
        Stack<String> s1 = new Stack<String>(); //符号栈
        //因为s2这个栈,在整个转换过程中,没有pop操作,而且后面还需要逆序输出
        //因此比较麻烦,这里我们就不用Stack<String> ,直接使用List<String > s2
        List<String> s2 = new ArrayList<String>(); //存放中间结果的栈

        //遍历ls
        for (String item : ls) {
            //如果是一个数,加入s2
            if (item.matches("\\d+")) {
                s2.add(item);
            } else if (item.equals("(")) {
                s1.push(item);
            } else if (item.equals(")")) {
                //如果是右括号“)”,则依次弹出s1栈顶的运算符,并压入s2,直到遇到左括号为止,
                //此时将这对括号丢掉
                while (!s1.peek().equals("(")) {
                    s2.add(s1.pop());
                }
                s1.pop();  //将 ( 弹出s1的栈,消除小括号
            } else {
                //当item的优先级小于等于栈顶运算符,
                //将s1栈顶的运算符弹出并加入s2中,再次转到(4.1)与s1中新的栈顶运算符相比较
                //问题:我们缺少一个比较优先级高低的方法
                while (s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item)) {
                    s2.add(s1.pop());
                }
                //还需要将item压入栈中,
                s1.push(item);
            }
        }
        //将s1中剩余的运算符依次弹出并加入s2
        while (s1.size() != 0){
            s2.add(s1.pop());
        }
        return s2;  //因为是存放到list,因此按顺序输出就是逆波兰表达式
    }

    //方法,将 中缀表达式转成对应的list
    public static List<String> toInfixExpressionList(String s) {
        //定义一个List,存放中缀表达式对应的内容
        List<String> ls = new ArrayList<>();
        int i = 0; //这是一个指针,用于遍历 中缀表达式字符串
        String str; //多位数的拼接
        char c; //每遍历到一个字符,就放入c
        do {
            //如果c是一个非数字,需要加入到ls
            if ((c = s.charAt(i)) < 48 || (c = s.charAt(i)) > 57) {
                ls.add("" + c);
                i++;  //i需要后移
            } else { //如果是一个数,需要考虑多位数
                str = ""; //先将str置为""
                while (i < s.length() && (c = s.charAt(i)) >= 48 && (c = s.charAt(i)) <= 57) {
                    str += c; //拼接
                    i++;
                }
                ls.add(str);
            }
        } while (i < s.length());
        return ls; //返回
    }

    //将一个逆波兰表达式,依次将数据和运算符,放入ArrayList中
    public static List<String> getListString(String suffixExpression) {
        //将suffixExpression分割
        String[] split = suffixExpression.split(" ");
        List<String> list = new ArrayList<String>();
        for (String ele : split) {
            list.add(ele);
        }
        return list;
    }

    //完成对逆波兰表达式的运算

    /**
     * 1. 从左至右扫描,将3和4压入堆栈;
     * 2. 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素),计算出3+4的值,得7,再将7入栈;
     * 3. 将5入栈;
     * 4. 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
     * 5. 将6入栈;
     * 6. 最后是-运算符,计算出35-6的值,即29,由此得出最终结果
     */
    public static int calculate(List<String> ls) {
        //创建一个栈,只需要一个栈
        Stack<String> stack = new Stack<>();
        //遍历ls
        for (String item : ls) {
            //这里使用正则表达式取出数
            if (item.matches("\\d+")) { // 匹配的是多位数
                //入栈
                stack.push(item);
            } else {
                //pop出两个数并运算,再入栈
                int num2 = Integer.parseInt(stack.pop());
                int num1 = Integer.parseInt(stack.pop());
                int res = 0;
                if (item.equals("+")) {
                    res = num1 + num2;
                } else if (item.equals("-")) {
                    res = num1 - num2;
                } else if (item.equals("*")) {
                    res = num1 * num2;
                } else if (item.equals("/")) {
                    res = num1 / num2;
                } else {
                    throw new RuntimeException("运算符有误");
                }
                //把res入栈
                stack.push(res + "");
            }
        }
        //最后留在stack中的数据就是运算结果
        return Integer.parseInt(stack.pop());
    }

}

//编写一个类Operation,返回一个运算符对应的优先级
class Operation {
    private static int ADD = 1;
    private static int SUB = 1;
    private static int MUL = 2;
    private static int DIV = 2;

    //写一个方法,返回对应的优先级数字
    public static int getValue(String operation) {
        int result = 0;
        switch (operation) {
            case "+":
                result = ADD;
                break;
            case "-":
                result = SUB;
                break;
            case "*":
                result = MUL;
                break;
            case "/":
                result = DIV;
                break;
            default:
                System.out.println("不存在该运算符");
                break;
        }
        return result;
    }
}

Your own test results.

Guess you like

Origin blog.csdn.net/weixin_41910694/article/details/92800576