Convert infix expression to suffix and solve calculation

Convert infix expression to postfix expression

Specific steps are as follows:

  1. Initialize two stacks: operator stack s1 and stack s2 for storing intermediate results;
  2. Scan the infix expression from left to right;
  3. When it encounters the operand, press it to s2;
  4. When encountering an operator, compare its priority with the operator on the top of the s1 stack:
    4.1 If s1 is empty, or the operator on the top of the stack is a left parenthesis "(", then this operator is directly pushed onto the stack;
    4.2 otherwise, if priority The level is higher than that of the operator on the top of the stack, and the operator is also pushed into s1;
    4.3 Otherwise, the operator on the top of the s1 stack is popped and pushed into s2, again to the new top of the stack in (4-1) and s1 Operator comparison;
  5. When encountering a parenthesis:
    5.1 If it is a left parenthesis "(", then directly press s1
    5.2 If it is a right parenthesis ")", the operators on the top of the s1 stack will be popped in turn, and s2 will be pressed until the left parenthesis is encountered, Discard this pair of brackets at this time
  6. Repeat steps 2 to 5 until the rightmost of the expression
  7. Pop the remaining operators in s1 one by one and push them into s2
  8. Pop up the elements in s2 in turn and output, the reverse order of the result is the postfix expression corresponding to the infix expression

For example:

The process of converting the infix expression "1+((2+3)×4)-5" into the postfix expression is as follows,
Insert picture description here
so the result is
"1 2 3 + 4 × + 5 –"

Code:

Method: Convert the infix expression to the corresponding List
String: "1+((2+3)×4)-5" to -" ArrayList: [1,+,(,(,2,+,3, ),*,4,),-,5]

public static List<String> toInfixExpressionList(String s) {
    
    
		//定义一个List,存放中缀表达式 对应的内容
		List<String> ls = new ArrayList<String>();
		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 置成"" '0'[48]->'9'[57]
				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;//返回
	}

Method: Get the List corresponding to the infix expression => List
ArrayList corresponding to the suffix expression : [1,+,(,(,2,+,3,),*,4,),-,5]

ArrayList:[1,2,3,+,4,*,+,5,-]

 //即 ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]  =》 ArrayList [1,2,3,+,4,*,+,5,–]
    //方法:将得到的中缀表达式对应的List => 后缀表达式对应的List
    public static List<String> parseSuffixExpreesionList(List<String> ls) {
    
    
        //定义两个栈
        Stack<String> s1 = new Stack<String>(); // 符号栈
        //说明:因为s2 这个栈,在整个转换过程中,没有pop操作,而且后面我们还需要逆序输出
        //因此比较麻烦,这里我们就不用 Stack<String> 直接使用 List<String> s2
        //Stack<String> s2 = new Stack<String>(); // 储存中间结果的栈s2
        List<String> s2 = new ArrayList<String>(); // 储存中间结果的Lists2
        //遍历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栈顶运算符, 将s1栈顶的运算符弹出并加入到s2中,再次转到(4.1)与s1中新的栈顶运算符相比较
                //问题:我们缺少一个比较优先级高低的方法
                while(s1.size() != 0 &&  getpriority(s1.peek()) >=  getpriority(item) ) {
    
    
                    s2.add(s1.pop());
                }
                //还需要将item压入栈
                s1.push(item);
            }
        }
        //将s1中剩余的运算符依次弹出并加入s2
        while(s1.size() != 0) {
    
    
            s2.add(s1.pop());
        }
        return s2; //注意因为是存放到List, 因此按顺序输出就是对应的后缀表达式对应的List
    }

Evaluation of postfix expressions

Scan the expression from left to right. When you encounter a number, push the number onto the stack. When you encounter an operator, pop the two numbers on the top of the stack, and use the operator to do the corresponding calculations on them (the next top element and the top element of the stack) ), and push the result to the stack; repeat the above process until the rightmost end of the expression, the final value obtained by the operation is the result of the expression

For example: (3+4)×5-6 corresponds to the suffix expression 3 4 + 5 × 6-, the evaluation steps for the suffix expression are as follows:

  1. Scan from left to right, push 3 and 4 onto the stack;
  2. Encounter the + operator, so pop 4 and 3 (4 is the top element on the stack, 3 is the next top element), calculate the value of 3+4, get 7, and then push 7 onto the stack;
  3. Put 5 into the stack;
  4. Next is the × operator, so 5 and 7 are popped out, 7×5=35 is calculated, and 35 is pushed onto the stack;
  5. Put 6 into the stack;
  6. Finally is the-operator, which calculates the value of 35-6, which is 29, which gives the final result

Code:

public static int calculate(List<String> ls) {
    
    
		// 创建给栈, 只需要一个栈即可
		Stack<String> stack = new Stack<String>();
		// 遍历 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());
	}

Complete code:
Insert picture description here


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

/**
 * @anthor longzx
 * @create 2021 01 24 14:41
 * @Description
 **/
public class PolandNotation {
    
    
    public static void main(String[] args) {
    
    
        String expression = "1+((2+3)*4)-5";//注意表达式
        List<String> infixExpressionList = toInfixExpressionList(expression);
        System.out.println("中缀表达式对应的List=" + infixExpressionList); // ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]
        List<String> suffixExpreesionList = parseSuffixExpreesionList(infixExpressionList);
        System.out.println("后缀表达式对应的List" + suffixExpreesionList); //ArrayList [1,2,3,+,4,*,+,5,–]
        System.out.printf("expression=%d", calculate(suffixExpreesionList)); // ?

    }

    //方法:将 中缀表达式转成对应的List
    //  s="1+((2+3)×4)-5";
    public static List<String> toInfixExpressionList(String s) {
    
    
        //定义一个List,存放中缀表达式 对应的内容
        List<String> ls = new ArrayList<String>();
        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 置成"" '0'[48]->'9'[57]
                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 [1,+,(,(,2,+,3,),*,4,),-,5]  =》 ArrayList [1,2,3,+,4,*,+,5,–]
    //方法:将得到的中缀表达式对应的List => 后缀表达式对应的List
    public static List<String> parseSuffixExpreesionList(List<String> ls) {
    
    
        //定义两个栈
        Stack<String> s1 = new Stack<String>(); // 符号栈
        //说明:因为s2 这个栈,在整个转换过程中,没有pop操作,而且后面我们还需要逆序输出
        //因此比较麻烦,这里我们就不用 Stack<String> 直接使用 List<String> s2
        //Stack<String> s2 = new Stack<String>(); // 储存中间结果的栈s2
        List<String> s2 = new ArrayList<String>(); // 储存中间结果的Lists2
        //遍历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栈顶运算符, 将s1栈顶的运算符弹出并加入到s2中,再次转到(4.1)与s1中新的栈顶运算符相比较
                //问题:我们缺少一个比较优先级高低的方法
                while(s1.size() != 0 &&  getpriority(s1.peek()) >=  getpriority(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 int getpriority(String s){
    
    
    int result = 0;
    switch (s) {
    
    
        case "+":
            result = 1;
            break;
        case "-":
            result = 1;
            break;
        case "*":
            result = 2;
            break;
        case "/":
            result = 2;
            break;
        default:
            break;
    }
    return result;
}

    //完成对逆波兰表达式的运算
	/*
	 * 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<String>();
        // 遍历 ls
        int num2 =0;
        int num1 =0;
        int res = 0;
        for (String item : ls) {
    
    
            // 这里使用正则表达式来取出数
            if (item.matches("\\d+")) {
    
     // 匹配的是多位数
                // 入栈
                stack.push(item);
            } else {
    
    
                // pop出两个数,并运算, 再入栈
                 num2 = Integer.parseInt(stack.pop());
                 num1 = Integer.parseInt(stack.pop());
                 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());
    }
}

Guess you like

Origin blog.csdn.net/qq_41784749/article/details/113089513