【Data structure】_5. Stack

Table of contents

1. Concept

2. The use of the stack

2.1 Method

2.2 Examples

3. Simulation implementation of the stack

4. Application scenarios of the stack

4.1 Problem 1: Impossible pop sequence

4.2 Topic 2: Print singly linked list in reverse order

4.3 Topic 3: Reverse Polish expression evaluation

4.4 Topic 4: Bracket matching

4.5 Topic 5: Stack push and pop training

4.6 Topic 6: Minimum stack


1. Concept

(1) A stack is a special linear table that only allows insertion and deletion of elements at one fixed end.

(2) One end of the data insertion and deletion operation is called the top of the stack, and the other end is called the bottom of the stack.

(3) The data elements in the stack follow the principle of last in first out;

(4) Push stack: The insertion operation of the stack is called push or push or push, and the incoming data is at the top of the stack;

         Popping: The deletion operation of the stack is called popping, and the data is at the top of the stack;

2. The use of the stack

2.1 Method

method Function
Stack() construct an empty stack
And push(And e) push e onto the stack and return e
And pop() Pop the top element of the stack and return
E peek() Get the top element of the stack
int size() Get the number of valid elements in the stack
boolean empty() Check if the stack is empty

2.2 Examples

    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        for(int i=0;i<=5;i++){
            stack.push(i);  // 压栈
        }
        // 获取栈顶元素
        System.out.println(stack.peek());
        Integer a = stack.pop();  // 出栈栈顶元素
        System.out.println(a);
        System.out.println(stack.peek());
        System.out.println(stack.size());
    }

3. Simulation implementation of the stack

Stack inherits from Vector. Checking the source code of Vector shows that vector is internally implemented with an array, so the simulation implementation uses an array stack;

(1) Package class relationship:

(2)MyStack:

package TestMyStack;

import java.util.Arrays;

public class MyStack {
    public int[] elem;
    public int useSize;
    public MyStack(){
        this.elem = new int[10];
    }
    // 压栈
    public void push(int val){
        if(isFull()){
            // 扩容
            reSize();
        }
        elem[useSize] = val;
        this.useSize++;
    }
    // 判满
    public boolean isFull(){
        if(elem.length == this.useSize){
            return true;
        }
        return false;
    }
    // 扩容
    public void reSize(){
        elem = Arrays.copyOf(elem, 2*elem.length);
    }
    // 出栈并返回出栈元素
    public int pop(){
        if(isEmpty()){
            throw new EmptyException();
        }
//        int val = elem[this.useSize-1];
//        this.useSize--;
//        return val;
        return this.elem[--this.useSize];
    }
    // 判空
    public boolean isEmpty(){
        return this.useSize==0;
    }
    // 获取栈顶元素
    public int peek(){
        return this.elem[this.useSize-1];
    }
}

(3)EmptyException:

package TestMyStack;

public class EmptyException extends RuntimeException{
    public EmptyException(){

    }
}

4. Application scenarios of the stack

4.1 Problem 1: Impossible pop sequence

If the push sequence is 1, 2, 3, 4, and the stack can be popped during the push process, then the impossible pop sequence is: C A.
1, 4, 3, 2 B. 2, 3, 4, 1 C .3,1,4,2 D.3,4,2,1

4.2 Topic 2: Print singly linked list in reverse order

(1) Recursive reverse order printing method of singly linked list:

 public void fun1(ListNode pHead){
        // 递归逆序打印单链表
        if(pHead == null){
            return;
        }
        if(pHead.next == null){
            System.out.println(pHead.val);
        }
        fun1(pHead.next);
        System.out.println(pHead.val);
    }

(2) Circular recursive reverse order printing method of singly linked list:

public void fun2(ListNode pHead){
        Stack<ListNode> stack = new Stack<>();
        ListNode cur = head;
        while(cur!=null){
            stack.push(cur);
            cur = cur.next;
        }
        // 遍历栈
        while(!stack.isEmpty()){
            ListNode top = stack.pop();
            System.out.print(top.val+" ");
        }
        System.out.println();
    }

4.3 Topic 3: Reverse Polish expression evaluation

Topic Link: 150. Reverse Polish Expression Evaluation - LeetCode

Problem-solving idea: Traverse the array of suffix arithmetic expressions, if it is data, push it onto the stack, if it is an arithmetic operator, pop the top two elements of the stack as the post operand and pre operand respectively, then push the calculation result onto the stack, and continue backward Traverse the array and loop until there is only one element in the stack, which is the final value;

code:

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for(String x: tokens){
            if(!isOperation(x)){
                stack.push(Integer.parseInt(x));
            }else{
                int num2 = stack.pop();
                int num1 = stack.pop();
                switch(x){
                    case "+":
                        stack.push(num1+num2);
                        break;
                    case "-":
                        stack.push(num1-num2);
                        break;
                    case "*":
                        stack.push(num1*num2);
                        break;
                    case "/":
                        stack.push(num1/num2);
                        break;
                }
            }
        }
        return stack.pop();
    }
    private boolean isOperation(String x){
        if(x.equals("+")||x.equals("-")||x.equals("*")||x.equals("/")){
            return true;
        }
        return false;
    }
}

4.4 Topic 4: Bracket matching

Topic link: 20. Effective parentheses - LeetCode

code:

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack();
        for(int i=0;i<s.length();i++){
            char ch = s.charAt(i);
            if(ch=='(' || ch=='{' || ch=='['){
                stack.push(ch);
            }else{
                // 第一种情况:第一个就是右括号,没有元素入栈,栈为空,直接返回假
                if(stack.empty()){
                    return false;  
                }
                //  第二种情况:栈不为空,判断是否匹配
                char ch2 = stack.peek();   //栈顶元素,必为左括号
                if(ch2 == '('&& ch == ')' || ch2 == '{' && ch == '}' || ch2 == '[' && ch == ']'){
                    stack.pop();
                }else{
                    return false;
                }
            }
        }
        if(!stack.empty()){
            return false;
        }
        return true;
    }
}

4.5 Topic 5: Stack push and pop training

Topic Link: Stack Push and Pop Sequences

Problem-solving idea: Define i subscript to traverse pushV, j subscript to traverse popV, and push the elements of pushV to the stack. When the two elements are not equal, continue to push the pushV element; when the two elements are equal, pop the top element of the stack , both i and j are ++;

code:

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param pushV int整型一维数组 
     * @param popV int整型一维数组 
     * @return bool布尔型
     */
    public boolean IsPopOrder (int[] pushV, int[] popV) {
        Stack<Integer> stack = new Stack<>();
        int j=0;
        for(int i=0;i<pushV.length;i++){
            stack.push(pushV[i]);
            while(j<popV.length && !stack.empty() && stack.peek().equals(popV[j])){
                stack.pop();
                j++;
            }
        }
        return stack.empty();
    }
}

4.6 Topic 6: Minimum stack

Topic Link: 155. Minimal Stack - LeetCode

Problem-solving idea: open up a stack for storing the minimum value for the target stack, traverse the target stack in turn, and put the smallest element into the stack. The top element of the minimum stack is the smallest element of the target stack, and the minimum value can be retrieved in constant time element;

code:

class MinStack {
    private Stack<Integer> stack;
    private Stack<Integer> minStack;
    public MinStack() {
        stack = new Stack<>();
        minStack = new Stack<>();
    }
    public void push(int val) {
        stack.push(val);
        if(minStack.empty()){
            minStack.push(val);
        }else{   //minStack不为空
            if(val <= minStack.peek()){  
                // 如果要插入的值比minStack的栈顶元素小
                minStack.push(val); 
                // 注意当val==minStack栈顶元素时,也需要将该元素入栈minStack
                // 因为stack出栈元素时,如果该元素是minStack中的元素,该元素也需要出栈
                // 以保证在出栈stack最小元素时,minStack中的最小元素不受影响

            }
        }
    }
    
    public void pop() {
        if(!stack.empty()){
            Integer val = stack.pop();
            if(val.equals(minStack.peek())){
                minStack.pop();
            }
            // 如果对元素拆箱为int类型,就可使用==进行判等
        }
    }
    
    public int top() {
       if(!stack.empty()){
           return stack.peek();
       }
       return -1;
    }
    
    public int getMin() {
        return minStack.peek();
    }
}

Guess you like

Origin blog.csdn.net/m0_63299495/article/details/131945572