Stack
Introduction of stack
(1) Introduction of stack
(2) Introduction to stack
- Stack (stack)
- A stack is an ordered list of Filo first in last out.
- Stack is a special linear table that restricts the insertion and deletion of elements in a linear table to the same end of the linear table. The end that allows insertion and deletion is the changing end, which is called the top of the stack, and the other end is the fixed end, which is called the bottom of the stack.
- According to the definition of stack, the first element put in the stack is at the bottom of the stack, the last element put in is at the top of the stack, while the deleted element is just the opposite. The last element put in is deleted first, and the first element is deleted last
(3) pop and push
(4) Application scenario of stack
- Subroutine call: before jumping to the subroutine, the address of the next instruction will be stored in the stack until the subroutine is executed, and then the address will be taken out to return to the original program.
- Handling recursive calls: similar to subroutine calls, except that in addition to storing the address of the next instruction, parameters, area variables and other data are also stored in the stack.
- Expression conversion [infix expression to suffix expression] and evaluation (actual solution).
- Traversal of binary tree.
- The depth first search method of graphics.
Implementation of stack
(1) Thought analysis of realizing stack
- Use arrays to simulate stacks
- Define a top to represent the top of the stack and initialize it to - 1
- When data is added to the stack, top++; stack[top] = data;
- Stack out operation, int value = stack[top]; top--, return value
(2) Code implementation
//Define a class to represent the stack structure class ArrayStack{ private int maxSize;//Stack size private int[] stack;//Array, array simulation stack, array is placed in the array private int top = -1;//Stack top //constructor public ArrayStack(int maxSize) { this.maxSize = maxSize; stack = new int[this.maxSize]; } //Stack full public boolean isFull() { return top == maxSize-1; } //Stack empty public boolean isEmpty() { return top == -1; } //Push public void push(int value) { //Determine whether the stack is full if(isFull()) { System.out.println("Stack full"); return; } top++; stack[top]=value; } //Out of stack public int pop() { //First judge whether the stack is empty if(isEmpty()) { //Throw exception throw new RuntimeException("Stack empty, no data//"); } int value = stack[top]; top--; return value; } //Display the stack [traverse the stack]. When traversing, you need to display data from the top of the stack public void list() { //First judge whether the stack is empty if(isEmpty()) { //Throw exception throw new RuntimeException("Stack empty, no data//"); } for(int i = top;i>=0;i--) { System.out.printf("stack[%d]=%d \n",i,stack[i]); } } }
Use the stack to complete the evaluation of an expression (infix expression)
(1) Train of thought analysis
- Through an index value (index), we iterate through our expression
- If we find that it is a number, we will directly enter the number stack
- If it is found that a symbol is scanned, it can be divided into the following situations
3.1 if the current symbol stack is found to be empty, it will be directly put into the stack
3.2 if there are operators in the symbol stack, compare them. If the priority of the current operator is less than or equal to that of the operators in the stack, you need to pop two numbers from the number stack, pop a symbol from the symbol stack, and carry out the operation. The result will be put into the number stack, and then put the current operator into the symbol stack, If the priority of the current operator is higher than that of the operator on the stack, it is directly put into the symbol stack - When the expression is scanned, pop out the corresponding numbers and symbols from the number stack and symbol stack in sequence and run
- Finally, there is only one number on the number stack, which is the result of the expression
(2) Code implementation
package NO03; public class Calculator { public static void main(String[] args) { //Complete the operation of the expression according to the idea String expression = "70+2*6-4"; //Create two stacks, number stack and symbol stack ArrayStack2 numStack = new ArrayStack2(10); ArrayStack2 operStack = new ArrayStack2(10); //Define the required related variables int index = 0;//For scanning int num1 = 0; int num2 = 0; int oper = 0; int res = 0; char ch = ' ';//Save the char obtained from each scan to ch String keepNum = "";//Multi bit number for splicing //Start scan expression for while loop while (true) { //Get each character of expression in turn ch = expression.substring(index, index+1).charAt(0); //Judge what ch is, and then deal with it accordingly if(operStack.isOper(ch)) {//If operator //Judge whether the current symbol stack is empty if(!operStack.isEmpty()) { //handle //If the priority of the current operator is less than or equal to the operator in the stack, you need to pop out two numbers from the number stack, //pop out a symbol from the symbol stack, perform the operation, get the result, put it into the number stack, and then put the current operator into the symbol stack if(operStack.priority(ch)<=operStack.priority(operStack.peek())) { num1 = numStack.pop(); num2 = numStack.pop(); oper = operStack.pop(); res = numStack.cal(num1, num2, oper); //Put the result of the operator on the stack numStack.push(res); //Then put the current operator on the symbol stack operStack.push(ch); }else {//If the priority of the current operator is higher than that of the operator on the stack, it is directly put into the symbol stack operStack.push(ch); } }else { //If empty, direct access symbol stack operStack.push(ch); } }else {//If we find that it is a number, we will directly enter the number stack // numStack.push(ch-48);// The difference between character 1 and digit 1 in ascall code table is 48 //When processing a multi digit number, it cannot be found that it is a single digit and immediately put on the stack, because it may be a multi digit number //When processing numbers, you need to look at one bit after the index of the expression. If it is a number, it will be scanned. If it is a symbol, it will be put on the stack //Therefore, we need to define a variable string for splicing //Number of processing bits keepNum+=ch; //If ch is already the last bit of expression, it is directly put on the stack if(index==expression.length()-1) { numStack.push(Integer.parseInt(keepNum)); }else { //Judge whether the next character is a number. If it is a number, it will continue to scan. If it is an operator, it will be put on the stack if(operStack.isOper(expression.substring(index+1, index+2).charAt(0))) { //If the last bit is an operator, it is stacked numStack.push(Integer.parseInt(keepNum)); //important!!!!!. keepNum empty keepNum = ""; } } } //Let index+1 and judge whether to scan to the end of expression index++; if(index>=expression.length()) { break; } } //When the expression is scanned, pop out the corresponding numbers and symbols from the number stack and symbol stack in sequence and run while (true) { //If the symbol stack is empty, the final result will be calculated, and there is only one number [result] in the number stack if(operStack.isEmpty()) { break; } num1 = numStack.pop(); num2 = numStack.pop(); oper = operStack.pop(); res = numStack.cal(num1, num2, oper); numStack.push(res);//Push } //pop out the last number of the stack and calculate the result System.out.printf("expression%s = %d",expression,numStack.pop()); } } //Create a stack //Define a class to represent the stack structure, and the function needs to be extended class ArrayStack2{ private int maxSize;//Stack size private int[] stack;//Array, array simulation stack, array is placed in the array private int top = -1;//Stack top //constructor public ArrayStack2(int maxSize) { this.maxSize = maxSize; stack = new int[this.maxSize]; } //Stack full public boolean isFull() { return top == maxSize-1; } //Stack empty public boolean isEmpty() { return top == -1; } //Push public void push(int value) { //Determine whether the stack is full if(isFull()) { System.out.println("Stack full"); return; } top++; stack[top]=value; } //Out of stack public int pop() { //First judge whether the stack is empty if(isEmpty()) { //Throw exception throw new RuntimeException("Stack empty, no data//"); } int value = stack[top]; top--; return value; } //Display the stack [traverse the stack]. When traversing, you need to display data from the top of the stack public void list() { //First judge whether the stack is empty if(isEmpty()) { //Throw exception System.out.println("Stack empty, no data"); } for(int i = top;i>=0;i--) { System.out.printf("stack[%d]=%d \n",i,stack[i]); } } //Returns the priority of the operator. The priority is determined by the programmer. The priority is expressed in numbers //The higher the number, the higher the priority public int priority(int oper) { if(oper == '*'||oper == '/') { return 1; }else if (oper == '+'||oper == '-') { return 0; }else { return -1;//Assume that there are only +, -, *, in the current expression/ } } //Determine whether it is an operator public boolean isOper(char val) { return val=='+'||val=='-'||val=='*'||val=='/'; } //computing method public int cal(int num1,int num2,int oper) { int res=0;//Used to store calculation results switch (oper) { case '+': res = num1+num2; break; case '-': res = num2-num1;//Pay attention to the order break; case '*': res = num1*num2; break; case '/': res = num2/num1; break; default: break; } return res; } //Add a method to return the value at the top of the current stack, but it is not a real pop public int peek() { return stack[top]; } }
Note: the implementation of single digit operation is extended to multi digit operation
Prefix expression (Polish expression)
(1) Introduction:
- Prefix expression is also called polish. The operator of prefix expression precedes the operand
- Example: (3 + 4) × The prefix expression corresponding to 5-6 is- × + 3 4 5 6
(2) Computer evaluation of prefix expressions
Scan the expression from right to left. When encountering a number, push the number into the stack. When encountering an operator, pop up the two numbers at the top of the stack, use the operator to calculate them (top element and secondary top element), and put the result into the stack; Repeat the above process until the leftmost end of the expression. The value obtained by the final operation is the result of the expression
Suffix expression (inverse Polish expression)
(1) Introduction
- Suffix expressions, also known as inverse Polish expressions, are similar to prefix expressions, except that the operator is after the operand
- Example: (3 + 4) × The suffix expression corresponding to 5-6 is 3, 4 + 5 × 6 –
(2) Computer evaluation of suffix expressions
Scan the expression from left to right. When encountering a number, push the number into the stack. When encountering an operator, pop up the two numbers at the top of the stack, use the operator to calculate them (secondary top element and top element), and put the result into the stack; Repeat the above process until the rightmost end of the expression. The value obtained by the final operation is the result of the expression
(3) Complete an inverse Polish calculator
Task point:
- Enter an inverse Polish expression (suffix expression), use stack, and calculate the result
- It supports parentheses and multi digit integers, because here we mainly talk about data structures, so the calculator is simplified and only supports the calculation of integers.
- Train of thought analysis
- Code complete
Code implementation:
package NO03; import java.util.ArrayList; import java.util.List; import java.util.Stack; public class PolandNotation { public static void main(String[] args) { // First define an inverse Polish expression //(3+4) × The suffix expression corresponding to 5-6 is 3, 4 + 5 × 6 - //For convenience, the numbers and symbols of the inverse Polish expression are separated by spaces String suffixExpression = "30 4 + 5 * 6 -"; //Idea: //1. First "3 4 + 5" × 6 - "put in ArrayList //2. Pass the ArrayList to a method and traverse the matching stack to complete the calculation List<String> list = getListString(suffixExpression); System.out.println("List="+list); int res = calculate(list); System.err.println("The result of the calculation is:"+res); } //Put an inverse expression, and then put the data and operators into the ArrayList public static List<String> getListString(String suffixExpression){ //Split suffixExpression String[] split = suffixExpression.split(" "); List<String> list = new ArrayList<String>(); for(String ele:split) { list.add(ele); } return list; } //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. Stack 5; 4. Next is × Operator, so pop up 5 and 7 and calculate 7 × 5 = 35, put 35 into the stack; 5. Stack 6; 6. Finally, the - Operator calculates the value of 35-6, i.e. 29, to get the final result * */ public static int calculate(List<String> ls) { //To create a stack, you only need one Stack<String> stack = new Stack<String>(); //Traversal ls for(String item: ls ) { if(item.matches("\\d+")) { //Push stack.push(item); }else { //pop out two numbers, and operation, in 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 operation result return Integer.parseInt(stack.pop()); } }