3: Inverse Polish calculator

Posted by billabong0202 on Sat, 05 Mar 2022 02:15:01 +0100

1. Infix expression = > infix expression List

give an example:

  • Infix expression: 1 + ((2 + 3) × 4)-5
  • List corresponding to infix expression = [1, +, (, (, 2, +, 3,), *, 4,), -, 5]

Code implementation:

	//  s="1+((2+3)×4)-5";
	public static List<String> toInfixExpressionList(String s) {
		//Define a List to store the contents corresponding to infix expressions
		List<String> ls = new ArrayList<String>();
		int i = 0; //This is a pointer used to traverse the infix expression string
		String str; // Splicing of multi bit numbers
		char c; // Every time a character is traversed, it is put into c
		do {
			//If c is a non number, add to ls
			if((c=s.charAt(i)) < 48 ||  (c=s.charAt(i)) > 57) {
				ls.add("" + c);
				i++; //i need to move back
			} else { //If it is a number, multiple numbers need to be considered
				str = ""; //First set str to "" '0' [48] - [9 '[57]
				while(i < s.length() && (c=s.charAt(i)) >= 48 && (c=s.charAt(i)) <= 57) {
					str += c;//Splicing
					i++;
				}
				ls.add(str);
			}
		}while(i < s.length());
		return ls;//return
	}

Note:

  • Extract characters from String (s.charAt(i))
  • Judge whether it is a number (48 < = x < = 57) ['0' - > '9']
  • Method for judging whether a character is a multi bit number (while)

2. Infix expression List = > suffix expression List

give an example:
ArrayList [1,+,(,(,2,+,3,),,4,),-,5] => ArrayList [1,2,3,+,4,,+,5,–]

The specific steps are as follows:

  • 1: Initialize two stacks: operator stack s1 and stack s2 for storing intermediate results;

  • 2: Scan infix expression from left to right;

  • 3: When encountering an operand, press it to s2;

  • 4: When an operator is encountered, compare its priority with s1 stack top operator:

    • 1. If s1 is empty or the operator at the top of the stack is an open parenthesis "(", this operator will be directly put on the stack;
    • The priority is higher than that of the stack top operator, and the operator is also pushed into s1
    • Otherwise, pop up the operator at the top of the stack in s1 and press it into s2. Go to (4-1) again and compare it with the new operator at the top of the stack in s1
  • 5: When parentheses are encountered:

    • If it is the left parenthesis "(", press s1 directly
    • If it is the closing parenthesis ")", the operators at the top of s1 stack will pop up in turn and press s2 until the left parenthesis is encountered. At this time, this pair of parentheses will be discarded
  • 6: Repeat steps 2 through 5 until the rightmost part of the expression

  • 7: Pop up the remaining operators in s1 and press them into s2

  • 8: Pop up the elements in s2 in turn and output them. The reverse order of the result is the suffix expression corresponding to the infix expression

Code example:

//That is, ArrayList [1,+,(,(,2,+,3,),*,4,),-,5] = "ArrayList [1,2,3,+,4,*,+,5, –]
	//Method: List corresponding to infix expression = > List corresponding to suffix expression
	public static List<String> parseSuffixExpreesionList(List<String> ls) {
		//Define two stacks
		Stack<String> s1 = new Stack<String>(); // Symbol stack
		//Note: because s2 is a stack, there is no pop operation in the whole conversion process, and we need to output it in reverse order later
		//Therefore, it's troublesome. Here, we don't need stack < string > to directly use list < string > S2
		//Stack<String> s2 = new Stack<String>(); //  Stack S2 for storing intermediate results
		List<String> s2 = new ArrayList<String>(); // Lists2 for storing intermediate results

		//Traversal ls
		for(String item: ls) {
			//If it's a number, add s2
			if(item.matches("\\d+")) {
				s2.add(item);
			} else if (item.equals("(")) {
				s1.push(item);
			} else if (item.equals(")")) {
				//If it is the closing parenthesis ")", the operators at the top of s1 stack will pop up in turn and press s2 until the left parenthesis is encountered. At this time, this pair of parentheses will be discarded
				while(!s1.peek().equals("(")) {
					s2.add(s1.pop());
				}
				s1.pop();//!!!  Pop (out of s1 stack and eliminate parentheses
			} else {
				//When the priority of item is less than or equal to the top operator of s1 stack, pop up the top operator of s1 stack and add it to s2. Go to (4.1) again and compare it with the new top operator in s1
				//Problem: we lack a way to compare priorities
				while(s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item) ) {
					s2.add(s1.pop());
				}
				//You also need to push the item onto the stack
				s1.push(item);
			}
		}

		//Pop up the remaining operators in s1 and add s2
		while(s1.size() != 0) {
			s2.add(s1.pop());
		}

		return s2; //Note that because it is stored in the List, the output in order is the List corresponding to the corresponding suffix expression

	}

Note:

  • Definition of stack (Stack s1 = new Stack())
    • Add push() to the stack
    • peek() pop stack
  • Regular expression: judge whether it is a number (item.matches("\ \ d +")

3. Operation of inverse Polish expression

	//Complete the operation of the inverse Polish expression
	/*
	 * 1)Scan from left to right and press 3 and 4 into the stack;
		2)Encounter the + operator, so pop up 4 and 3 (4 is the top element of the stack and 3 is the secondary top element), calculate the value of 3 + 4, get 7, and then put 7 on the stack;
		3)Put 5 into the stack;
		4)Next is × Operator, so pop up 5 and 7 and calculate 7 × 5 = 35, put 35 into the stack;
		5)Put 6 into the stack;
		6)Finally, the - Operator calculates the value of 35-6, i.e. 29, so as to obtain the final result
	 */
	
	public static int calculate(List<String> ls) {
		// To create a stack, you only need one stack
		Stack<String> stack = new Stack<String>();
		// Traversal ls
		for (String item : ls) {
			// Regular expressions are used here to extract numbers
			if (item.matches("\\d+")) { // The number of multiple bits matches
				// Push 
				stack.push(item);
			} else {
				// pop out two numbers, operate them, and then put them on the stack
				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("Incorrect operator");
				}
				//Put res on the stack
				stack.push("" + res);
			}
			
		}
		//The last data left in the stack is the result of the operation
		return Integer.parseInt(stack.pop());
	}

}

4. Others

Writing a class Operation can return the priority corresponding to an operator

class Operation {
	private static int ADD = 1;
	private static int SUB = 1;
	private static int MUL = 2;
	private static int DIV = 2;
	
	//Write a method to return the corresponding priority number
	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("The operator does not exist" + operation);
			break;
		}
		return result;
	}
	
}

Complete the function of converting an infix expression into a suffix expression

//Complete the function of converting an infix expression into a suffix expression
		/*explain
		//1. 1+((2+3)×4)-5 => Turn to 1 2 3 + 4 × +  5 –
		//2. Because it is inconvenient to operate str directly, first set "1 + ((2 + 3) × 4) - 5 "=" List corresponding to the expression of infix
		//   I.e. "1 + ((2 + 3)) × 4)-5" => ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]
		//3. List corresponding to infix expression = > list corresponding to suffix expression
		//   That is, ArrayList [1,+,(,(,2,+,3,),*,4,),-,5] = "ArrayList [1,2,3,+,4,*,+,5, –]
		 */
		String expression = "1+((2+3)*4)-5";//Note the expression
		List<String> infixExpressionList = toInfixExpressionList(expression);
		System.out.println("Infix expression List=" + infixExpressionList); // ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]
		List<String> suffixExpreesionList = parseSuffixExpreesionList(infixExpressionList);
		System.out.println("Corresponding to suffix expression List" + suffixExpreesionList); //ArrayList [1,2,3,+,4,*,+,5,–]

		System.out.printf("expression=%d", calculate(suffixExpreesionList)); // ?


Full code:

package com.atguigu.stack;

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

public class PolandNotation {

	public static void main(String[] args) {


		//Complete the function of converting an infix expression into a suffix expression
		/*explain
		//1. 1+((2+3)×4)-5 => Turn to 1 2 3 + 4 × +  5 –
		//2. Because it is inconvenient to operate str directly, first set "1 + ((2 + 3) × 4) - 5 "=" List corresponding to the expression of infix
		//   I.e. "1 + ((2 + 3)) × 4)-5" => ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]
		//3. List corresponding to infix expression = > list corresponding to suffix expression
		//   That is, ArrayList [1,+,(,(,2,+,3,),*,4,),-,5] = "ArrayList [1,2,3,+,4,*,+,5, –]
		*/
		String expression = "1+((2+3)*4)-5";//Note the expression
		List<String> infixExpressionList = toInfixExpressionList(expression);
		System.out.println("Infix expression List=" + infixExpressionList); // ArrayList [1,+,(,(,2,+,3,),*,4,),-,5]
		List<String> suffixExpreesionList = parseSuffixExpreesionList(infixExpressionList);
		System.out.println("Corresponding to suffix expression List" + suffixExpreesionList); //ArrayList [1,2,3,+,4,*,+,5,–]

		System.out.printf("expression=%d", calculate(suffixExpreesionList)); // ?


	}



	//That is, ArrayList [1,+,(,(,2,+,3,),*,4,),-,5] = "ArrayList [1,2,3,+,4,*,+,5, –]
	//The suffix of the expression corresponding to List = > will be obtained
	public static List<String> parseSuffixExpreesionList(List<String> ls) {
		//Define two stacks
		Stack<String> s1 = new Stack<String>(); // Symbol stack
		//Note: because s2 is a stack, there is no pop operation in the whole conversion process, and we need to output it in reverse order later
		//Therefore, it's troublesome. Here, we don't need stack < string > to directly use list < string > S2
		//Stack<String> s2 = new Stack<String>(); //  Stack S2 for storing intermediate results
		List<String> s2 = new ArrayList<String>(); // Lists2 for storing intermediate results

		//Traversal ls
		for(String item: ls) {
			//If it's a number, add s2
			if(item.matches("\\d+")) {
				s2.add(item);
			} else if (item.equals("(")) {
				s1.push(item);
			} else if (item.equals(")")) {
				//If it is the closing parenthesis ")", the operators at the top of s1 stack will pop up in turn and press s2 until the left parenthesis is encountered. At this time, this pair of parentheses will be discarded
				while(!s1.peek().equals("(")) {
					s2.add(s1.pop());
				}
				s1.pop();//!!!  Pop (out of s1 stack and eliminate parentheses
			} else {
				//When the priority of item is less than or equal to the top operator of s1 stack, pop up the top operator of s1 stack and add it to s2. Go to (4.1) again and compare it with the new top operator in s1
				//Problem: we lack a way to compare priorities
				while(s1.size() != 0 && Operation.getValue(s1.peek()) >= Operation.getValue(item) ) {
					s2.add(s1.pop());
				}
				//You also need to push the item onto the stack
				s1.push(item);
			}
		}

		//Pop up the remaining operators in s1 and add s2
		while(s1.size() != 0) {
			s2.add(s1.pop());
		}

		return s2; //Note that because it is stored in the List, the output in order is the List corresponding to the corresponding suffix expression

	}


	//  s="1+((2+3)×4)-5";
	public static List<String> toInfixExpressionList(String s) {
		//Define a List to store the contents corresponding to infix expressions
		List<String> ls = new ArrayList<String>();
		int i = 0; //This is a pointer used to traverse the infix expression string
		String str; // Splicing of multi bit numbers
		char c; // Every time a character is traversed, it is put into c
		do {
			//If c is a non number, I need to add ls
			if((c=s.charAt(i)) < 48 ||  (c=s.charAt(i)) > 57) {
				ls.add("" + c);
				i++; //i need to move back
			} else { //If it is a number, multiple numbers need to be considered
				str = ""; //First set str to "" '0' [48] - [9 '[57]
				while(i < s.length() && (c=s.charAt(i)) >= 48 && (c=s.charAt(i)) <= 57) {
					str += c;//Splicing
					i++;
				}
				ls.add(str);
			}
		}while(i < s.length());
		return ls;//return
	}


	//Complete the operation of the inverse Polish expression

	public static int calculate(List<String> ls) {
		// To create a stack, you only need one stack
		Stack<String> stack = new Stack<String>();
		// Traversal ls
		for (String item : ls) {
			// Regular expressions are used here to extract numbers
			if (item.matches("\\d+")) { // The number of multiple bits matches
				// Push 
				stack.push(item);
			} else {
				// pop out two numbers, operate them, and then put them on the stack
				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("Incorrect operator");
				}
				//Put res on the stack
				stack.push("" + res);
			}

		}
		//The last data left in the stack is the result of the operation
		return Integer.parseInt(stack.pop());
	}

}

//Writing a class Operation can return the priority corresponding to an operator
class Operation {
	private static int ADD = 1;
	private static int SUB = 1;
	private static int MUL = 2;
	private static int DIV = 2;

	//Write a method to return the corresponding priority number
	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("The operator does not exist" + operation);
				break;
		}
		return result;
	}

}

result