Catalog
1. Basic concept of stack
2. Java simulation simple sequential stack implementation
3. Enhanced function stack
4. Using stack to realize string reverse order
5. Use stack to judge whether separator matches
6, summary
1. Basic concept of stack
Stack is also called stack or stack. As a data structure, stack is a special linear table that can only insert and delete at one end. It stores data according to the principle of first in and last out. The first in data is pressed into the bottom of the stack, and the last data is on the top of the stack. When it needs to read data, data will pop up from the top of the stack (the last data is read out by the first). The stack has a memory function. In the insertion and deletion of the stack, the pointer at the bottom of the stack does not need to be changed.
A stack is a special linear table that allows insertion and deletion at the same end. One end of the stack that allows insertion and deletion is called top, and the other end is bottom; the bottom of the stack is fixed, while the top of the stack is floating; when the number of elements in the stack is zero, it is called empty stack. Insertion is generally called PUSH, and deletion is called POP.
Since the stack data structure only allows operation at one end, it operates according to the principle of LIFO (last in first out). Stacks are also known as LIFO tables.
Here take the badminton barrel as an example. The badminton barrel is a stack. At the beginning, the badminton barrel was empty, that is, the empty stack. Then we put badminton into the stack one by one, that is, push into the stack. When we need to use badminton, we take it from the barrel, that is, pop out of the stack. But the first badminton we get is the last one we put in. 2. Java simulation simple sequential stack implementation
package com.ys.datastructure; public class MyStack { private int[] array; private int maxSize; private int top; public MyStack(int size){ this.maxSize = size; array = new int[size]; top = -1; } //Indentation data public void push(int value){ if(top < maxSize-1){ array[++top] = value; } } //Pop up stack top data public int pop(){ return array[top--]; } //Access stack top data public int peek(){ return array[top]; } //Judge whether the stack is empty public boolean isEmpty(){ return (top == -1); } //Determine if the stack is full public boolean isFull(){ return (top == maxSize-1); } }
Test:
package com.ys.test; import com.ys.datastructure.MyStack; public class MyStackTest { public static void main(String[] args) { MyStack stack = new MyStack(3); stack.push(1); stack.push(2); stack.push(3); System.out.println(stack.peek()); while(!stack.isEmpty()){ System.out.println(stack.pop()); } } }
Result:
The stack is implemented by array. An array, a value representing the maximum capacity and a top variable pointing to the top element of the stack are defined internally. The construction method creates a new stack according to the capacity specified by the parameters. The push() method presses the elements into the stack, points to the variable top at the top of the stack and adds one to make it point to a position above the original top data item, and stores a data in this position. The pop() method returns the element that the top variable points to, and then subtracts the top variable by one to remove the data item. Know that the top variable always points to the element at the top of the stack.
Problems:
① after the initialization capacity of the above stack is realized, the capacity of the later stack cannot be expanded (although the stack is not used to store a large amount of data). What if the later data volume exceeds the initial capacity? (automatic expansion)
② we use array to implement stack. When defining array type, we also specify the data type stored in the stack. Can the same stack store different types of data? (declared as Object)
③. The stack needs to initialize the capacity, and the stack elements implemented by the array are stored continuously. Can we not initialize the capacity? (implemented by linked list)
3. Enhanced function stack
For the above problems, the first one can automatically expand capacity, and the second one can store various types of data. The solutions are as follows: (the third one is introduced when talking about linked list)
This simulation Stack is in JDK source code, you can refer to the implementation of Stack class.
package com.ys.datastructure; import java.util.Arrays; import java.util.EmptyStackException; public class ArrayStack { //Array of storage elements, declared as Object type, can store any type of data private Object[] elementData; //Pointer to top of stack private int top; //Total stack capacity private int size; //Build a stack with capacity of 10 by default public ArrayStack(){ this.elementData = new Object[10]; this.top = -1; this.size = 10; } public ArrayStack(int initialCapacity){ if(initialCapacity < 0){ throw new IllegalArgumentException("Initial stack capacity cannot be less than 0: "+initialCapacity); } this.elementData = new Object[initialCapacity]; this.top = -1; this.size = initialCapacity; } //Indentation element public Object push(Object item){ //Whether expansion is needed isGrow(top+1); elementData[++top] = item; return item; } //Pop up top element public Object pop(){ Object obj = peek(); remove(top); return obj; } //Get stack top element public Object peek(){ if(top == -1){ throw new EmptyStackException(); } return elementData[top]; } //Judge whether the stack is empty public boolean isEmpty(){ return (top == -1); } //Delete top of stack element public void remove(int top){ //Stack top element set to null elementData[top] = null; this.top--; } /** * Whether to expand the capacity. If necessary, double it and return true. If not, return false * @param minCapacity * @return */ public boolean isGrow(int minCapacity){ int oldCapacity = size; //If the total capacity of the current element after being pushed into the stack is larger than the previously defined capacity, you need to expand the capacity if(minCapacity >= oldCapacity){ //Define the total stack capacity after expansion int newCapacity = 0; //Double the stack capacity (shift one bit left) to see if it exceeds the maximum range indicated by int type if((oldCapacity<<1) - Integer.MAX_VALUE >0){ newCapacity = Integer.MAX_VALUE; }else{ newCapacity = (oldCapacity<<1);//Move left one bit, equivalent to * 2 } this.size = newCapacity; int[] newArray = new int[size]; elementData = Arrays.copyOf(elementData, size); return true; }else{ return false; } } }
Test:
//Test the custom stack class ArrayStack //Create a stack with a capacity of 3, then add 4 elements, 3 int s and 1 String @Test public void testArrayStack(){ ArrayStack stack = new ArrayStack(3); stack.push(1); //System.out.println(stack.peek()); stack.push(2); stack.push(3); stack.push("abc"); System.out.println(stack.peek()); stack.pop(); stack.pop(); stack.pop(); System.out.println(stack.peek()); }
Result:
4. Using stack to realize string reverse order
We know that the stack is last in, first out. We can separate a string into single characters, and then push() characters into the stack one by one. In a pop() stack, it is displayed in reverse order. As follows:
Invert the string "how are you"!!!
ps: Here we use the above self-defined stack to achieve, you can ArrayStack Replace with JDK Own stack class Stack Try
//Reverse string @Test public void testStringReversal(){ ArrayStack stack = new ArrayStack(); String str = "how are you"; char[] cha = str.toCharArray(); for(char c : cha){ stack.push(c); } while(!stack.isEmpty()){ System.out.print(stack.pop()); } }
Result:
5. Use stack to judge whether separator matches
If we have written xml tags or html tags, we all know that < must match the latest > and [must also match the latest].
For example: This is a sign match, if it is abc] it is a mismatch.
For 12, we analyze the data in the stack: eliminate the data in case of correct matching
Finally, if the content in the stack is empty, the matching succeeds, otherwise, the matching fails!!!
//Separator match //push the stack when you meet the left separator, pop the stack when you meet the right separator, and see whether the stack separator matches the separator @Test public void testMatch(){ ArrayStack stack = new ArrayStack(3); String str = "12"; char[] cha = str.toCharArray(); for(char c : cha){ switch (c) { case '{': case '[': case '<': stack.push(c); break; case '}': case ']': case '>': if(!stack.isEmpty()){ char ch = stack.pop().toString().toCharArray()[0]; if(c=='}' && ch != '{' || c==']' && ch != '[' || c==')' && ch != '('){ System.out.println("Error:"+ch+"-"+c); } } break; default: break; } } }
6, summary
According to the characteristics of stack LIFO, we implement word inversion and separator matching. So in fact, stack is a conceptual tool, and we can imagine what functions can be realized. The stack makes programs less error prone by providing restricted access methods push() and pop().
For the implementation of stack, we will know that the time complexity of data in and out of stack is O(1), that is to say, the time consumed by stack operation does not depend on the number of data items in the stack, so the operation time is very short. What's more, we need to pay attention to the fact that the stack does not need to be compared and moved. Let's not add to the cake.