Integer calculator implementation of prefix, infix, postfix expression (reverse Polish expression) and reverse Polish expression

Infix expression

Infix expression is usually what we see in mathematics expression is a human class easy to read, easy to understand the expression, more in line with common practice the expression of human thinking

Such as: (3 * 4) + 20-50/2

Disadvantages: It is difficult to operate the computer .

Prefix expression

As the name implies, the symbol comes first and the number comes after, which becomes the prefix

For example:-* + 3 4 5 6, the corresponding infix expression is: (3 + 4) * 5-6

Prefix expression evaluation ideas:

Scan the expression from right to left. When encountering a number, directly push the number into a stack. When encountering an operator, pop the two numbers at the top of the stack, use the operator to perform arithmetic operations on them, and press the calculation result again On the stack, repeat this process until the entire expression is scanned, and the final number left on the stack is the final operation result .

For example, the prefix expression for example:-* + 3 4 5 6

  1. First, all the numbers on the right side are directly pushed onto the stack from right to left.
  2. Continue to scan, encounter the operator + sign, then pop 3 and 4 on the top of the stack, perform the addition operation, and put the result 7 on the stack
  3. Next is the operator *. At this time, 7 and 5 on the top of the stack are popped, multiplication is performed, and the result 35 is placed on the stack
  4. Finally, the operation sends the-sign. At this time, the 35 and 6 on the top of the stack are faded out, and the subtraction operation is performed. Note: At this time, follow the principle of first in and then out of the stack. After 35, enter the stack and exit before 6, so 35-6 = 29, finally put 29 into the stack, at this time the expression is scanned, and the last number in the stack is the result

Postfix expression (reverse Polish expression)

Arithmetic expression explanation: Baidu Encyclopedia

Postfix expression evaluation ideas:

When you encounter a number, push the number onto the stack. When you encounter a symbol, pop the top two numbers on the stack and use the modified operator to do the calculation ( calculation order: next-top element operator stack top element ), then push the calculation result into the stack, repeat The above operations until the expression scan is completed, and the last number in the stack is the expression result.

For example: (3 + 4) * 5-6 suffix expression is 3 4 + 5 * 6-

  1. Push 3 and 4 onto the stack
  2. Scan to the + sign, pop 4 and 3 (4 is the top element on the stack, 3 is the next top element), calculate the addition, the result is 7, and push it onto the stack
  3. Scan to 5 and push it onto the stack
  4. Scan to *, pop 5 and 7, calculate the multiplication, and push the result 35 onto the stack
  5. Scan to 6 and push it onto the stack
  6. Scan to -, pop 6, calculate 35-6, result 29 is pushed onto the stack

Inverse Polish calculator implementation

A calculator that supports simple calculations of parentheses and multiple integers

The answer to the realization idea is divided into two parts:

  1. Infix expression to postfix expression
  2. Calculate the result based on the suffix expression

Infix expression to postfix expression rule

We don’t need to discuss the rules of infix-to-suffix expressions more, because it belongs to an invented algorithm. We only care about how to use this algorithm now. The rules are as follows:

  • 1. Initialize two stacks: operator stack s1 and result stack s2
  • 2. Scan the expression from left to right
  • 3. When you encounter a number, press s2 directly
  • 4. When encountering a symbol, it needs to compare its priority with the symbol on the top of the s1 stack, and meet the following rules
4.1 If s1 is empty, or the top operator of s1 is ( Put this symbol directly on the stack s1
4.2 If the symbol has a higher priority than the top operator Put this symbol directly on the stack s1
4.3 If the rules of 4.1 and 4.2 are not met Pop the operator at the top of the s1 stack into s2, and judge again according to 4.1
  • 5. When encountering brackets, meet the following rules
if ( Press directly into s1
if ) Pop the operators at the top of the s1 stack in turn, and push these operators into s2 until they encounter (, at this time, discard this pair of ()
  • 6. Repeat the judgment from 2 to 5 until the rightmost of the expression
  • 7. Pop up the remaining operators in s1 and push them into s2
  • 8. Pop up the elements in s2 in turn, and arrange them in flashback of the result, which is the obtained suffix expression

Code

package com.leolee.dataStructure.stack;

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

/**
 * @ClassName ReversePolishNotation
 * @Description: 逆波兰表达式
 * @Author LeoLee
 * @Date 2020/9/17
 * @Version V1.0
 **/
public class ReversePolishNotation {

    /*
     * 功能描述: <br> 对逆波兰表达式进行“格式处理”,转为List
     * 〈〉
     * @Param: [reversePolishNotationExpressions]
     * @Return: java.util.List<java.lang.String>
     * @Author: LeoLee
     * @Date: 2020/9/17 18:08
     */
    public static List<String> getListString(String reversePolishNotationExpressions) {

        String[] stringArray = reversePolishNotationExpressions.split(" ");
        List<String> list = new ArrayList<String>();
        for (String s : stringArray) {
            list.add(s);
        }
        return list;
    }

    /*
     * 功能描述: <br> 计算波兰表达式
     * 〈〉
     * @Param: [list] 后最表达式对应的list
     * @Return: int
     * @Author: LeoLee
     * @Date: 2020/9/17 18:33
     */
    public static int calculate (List<String> list) {

        Stack<String> stack = new Stack<String>();

        for (String item : list) {
            //判断字符是数字还是符号
            if (item.matches("\\d+")) {
                //匹配数字直接入栈
                stack.push(item);
            } else {
                //如果是符号,贼需要弹出两个元素进行运算
                int num2 = Integer.valueOf(stack.pop());//栈顶元素
                int num1 = Integer.valueOf(stack.pop());//次顶元素
                int result = 0;
                switch (item.charAt(0)) {
                    //计算顺序:次顶元素 运算符 栈顶元素
                    case '+' :
                        result = num1 + num2;
                        stack.push(String.valueOf(result));
                        break;
                    case '-' :
                        result = num1 - num2;
                        stack.push(String.valueOf(result));
                        break;
                    case '*' :
                        result = num1 * num2;
                        stack.push(String.valueOf(result));
                        break;
                    case '/' :
                        result = num1 / num2;
                        stack.push(String.valueOf(result));
                        break;
                    default:
                        throw new RuntimeException("不支持的运算符");
                }
            }
        }
        return Integer.valueOf(stack.pop());
    }

    /*
     * 功能描述: <br> 中缀表达式转换为 list,主要是为了处理多位数
     * 〈〉
     * @Param: [normalExpression] 中缀表达式
     * @Return: java.util.List<java.lang.String>
     * @Author: LeoLee
     * @Date: 2020/9/17 21:54
     */
    public static List<String> normalExpressionToList (String normalExpression) {

        List<String> list = new ArrayList<String>();
        char c;//用于转存每一个字符
        String str;//用于多位数拼接

        for (int i = 0; i < normalExpression.length(); i++) {
            c = normalExpression.charAt(i);
            //判断是数字还是符号
            if (String.valueOf(c).matches("\\d+")) {//数字处理
                str = "";
                //0~9 对应的 ASC码为 48~57,不在该范围则跳出循环
                while (i < normalExpression.length() && (c = normalExpression.charAt(i)) >= 48 && (c = normalExpression.charAt(i)) <= 57) {
                    str += c;
                    i++;
                }
                i--;
                list.add(str);
            } else {//符号处理
                list.add(String.valueOf(c));
            }
        }
        return list;
    }


    /*
     * 功能描述: <br> 中缀表达式字符list 转 后缀表达式字符list
     * 〈〉
     * @Param: [sourceList] 中缀表达式字符list
     * @Return: java.util.List<java.lang.String> 后缀表达式字符list
     * @Author: LeoLee
     * @Date: 2020/9/17 22:10
     */
    public static List<String> getReversePolishNotationList (List<String> sourceList) {

        Stack<String> s1 = new Stack<String>();//符号栈
        //Stack<String> s2 = new Stack<String>();//结果栈
        //由于s2栈在整个处理过程中不需要pop(),只会压入元素,最后取出结果还要倒叙输出,所以在这里使用List
        List<String> s2 = new ArrayList<String>();

        for (String item : sourceList) {
            if (item.matches("\\d+")) {//如果是一个数字则入s2
                s2.add(item);
            } else if ("(".equals(item)) {//如果是 (,直接压入s1
                s1.push(item);
            } else if (")".equals(item)) {//如果是 )	依次弹出s1栈顶的运算符,并将这些运算符压入s2,直到遇到 ( 为止,此时将这一对 () 丢弃
                while (!s1.peek().equals("(")) {//peek()只查看栈顶元素,并不弹出
                    s2.add(s1.pop());
                }
                s1.pop();//丢弃s1中的 (
            } else {
                //4.1 如果s1为空,或者s1栈顶运算符为 (	直接将此符号入栈s1
                //4.2 如果该符号比栈顶运算符优先级高	直接将此符号入栈s1
                //4.3 如果不满足 4.1 和 4.2 规则	将s1栈顶的运算符弹出压入s2中,再次根据 4.1 判断
                while (s1.size() != 0 && OperatorPriority.getValue(s1.peek()) >= OperatorPriority.getValue(item)) {//即4.3的判断条件,item小于等于栈顶运算符的优先级
                    s2.add(s1.pop());
                }
                s1.push(item);
            }
        }
        //将s1中剩余的运算符依次弹出并压入s2
        while (s1.size() != 0) {
            s2.add(s1.pop());
        }
        return s2;
    }

    //运算符优先级枚举类
    enum OperatorPriority {
        DIVIDE("/", 2),
        MULTIPLY("*", 2),
        ADD("+", 1),
        SUBTRACT("-", 1)
        ;

        private String key;
        private int val;

        private OperatorPriority (String key, int val) {
            this.key = key;
            this.val = val;
        }

        public static int getValue (String key) {

            ReversePolishNotation.OperatorPriority[] operations = ReversePolishNotation.OperatorPriority.values();
            for (int i = 0; i < operations.length; i++) {
                if (operations[i].getKey().equals(key)) {
                    return operations[i].getVal();
                }
            }
            //匹配不到则返回0
            return 0;
        }

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public int getVal() {
            return val;
        }

        public void setVal(int val) {
            this.val = val;
        }
    }

    public static void main(String[] args) {

        String normalExpression = "1+(30*3)/2+23-2";

        List<String> list = ReversePolishNotation.normalExpressionToList(normalExpression);
        List<String> reversePolishNotationList = ReversePolishNotation.getReversePolishNotationList(list);
        int result = ReversePolishNotation.calculate(reversePolishNotationList);
        System.out.println("1+(30*3)/2+23-2=" + result);
    }
}

 

Guess you like

Origin blog.csdn.net/qq_25805331/article/details/108652008