Graphical Java Stack stack

Posted by rptasiuk on Tue, 07 Dec 2021 17:12:14 +0100

Write in front

From a certain point of view, the LIFO (last in first out) feature of the stack is a very useful feature, which makes the stack particularly important.

The so-called LIFO is the last in first out, and the last in elements go out first, just as in the figure below.

In Java, the Java class library has provided us with a Stack class to implement the Stack, and this Stack class is a paradigm class, which can store different data types.

Then let's take a look at the Stack class methods provided by Java.

In these methods, a very frequent concept is the stack top object, because we know that the stack is a deep data structure like a well, and we can't see the overall structure of the stack standing on it. We can only see the top element, which is called the stack top element.
It has many functions. To some extent, various operations of the stack are inseparable from the top element of the stack.

Let's analyze one by one:
Determine whether the stack is empty:
When we stand above and look into the well, if we see something, in other words, we see the top element of the stack, then the well is not empty. Therefore, the stack top element can determine whether the stack is empty.

View stack top object:
Many times, after we know that the stack is not empty, we also need to know what the top element of the stack is, because when we operate on the stack, we can only see the top element of the stack. If we want to take it out or add another layer on its head, there is a premise that we see it, so we give the top element a name peek for operation.

Therefore, for peek, we have two common operations, one is to take it out, and the other is to add another layer on its head.
Then two methods are introduced: pop and push.

pop is to push out the top element peak, and then the next layer of peak becomes a new peak. If there is no next layer, the stack is empty.

push is to put a new element into the stack, and this element becomes a new peak.

OK, we are familiar with the basic operation of Stack. Next, let's take a simple example to use these methods of Stack class:

import java.util.Stack;
/**
 * Java Stack Basic use of
 * 
 * @Author (yequan17)
 * @Version (2021.12.6)
 */
public class JStackTest
{
    public static void main(String[] args){
        System.out.println("Integer Type:");
        Stack<Integer> stack=new Stack<Integer>();
        stack.push(1);
        stack.push(2);
        System.out.println("After adding the element, the top element of the stack is:"+stack.peek()+" Is it empty:"+stack.empty()+" All elements in the stack:"+stack);
        stack.pop();
        stack.pop();
        System.out.println("After removing elements:");
        System.out.println("Is it empty:"+stack.empty());
        
        System.out.println();
        System.out.println("Custom type:");
        Stack<MyObject> stackObject=new Stack<MyObject>();
        stackObject.push(new MyObject(3,"yequan3"));
        stackObject.push(new MyObject(4,"yequan4"));
        System.out.println("Stack top element after adding element:" +stackObject.peek().name+ " Is it empty:"+stackObject.empty());
        stackObject.pop();
        stackObject.pop();
        System.out.println("After removing elements");
        System.out.println("Is it empty:"+stackObject.empty());
    }
    
    static class MyObject{
        Integer id;
        String name;
        
        MyObject(int id,String name){
            this.id=id;
            this.name=name;
        }
    }
}

In the above code, we have briefly seen some methods of Stack class in Java. Next, we will implement the following Stack by ourselves.

Two implementations of stack

Stack can be realized by array and linked list.

These two methods have their own advantages and disadvantages:

  1. Using array to create stack can get continuous memory space, but it will be troublesome to expand capacity.
  2. Using linked list to realize stack expansion is simple, but the memory space is discontinuous.

Next, let's take a look at how to implement the stack with an array.

Stack with array: you only need to define a stack top pointer to point to the stack top element. When you want to add data, the pointer moves back, and when you want to take out data, the pointer moves forward.

When entering the stack, if the stack is full, you need to expand the memory. When leaving the stack, if the stack is empty, null is returned.

The specific codes are as follows:

import java.util.Arrays;
/**
 * Stack Array implementation of
 * 
 * @Author (yequan17)
 * @Version (2021.12.7)
 */
public class JStackArray
{
    //Template type. Specify the data type when creating
    public static class ArrayStack<E>{
        private Object[] stack;
        private int index;
        ArrayStack() {
            stack=new Object[10];
            index=0;//Stack top address
        }
        
        public boolean isEmpty(){
            return index==0;
        }
        
        public  E peek(){
            if(isEmpty()){
                return null;
            }
            return (E)stack[index-1];
        }
        
        public E pop(){
            if (isEmpty()) {
            return null;
            }
            index--;
            return (E)stack[index];
        }
        
        //Expand memory
        private void ensureCapacity(int index) {
            if (index > stack.length) {
                int len = stack.length + 10;
                stack = Arrays.copyOf(stack, len);
            }
        }

        public E push(E e) {
            ensureCapacity(index+1);
            stack[index++] = e;
            return e;
        }
    }
    
    public static void main(String[] args){
        ArrayStack<String> stack = new ArrayStack<>();
        stack.push("a");
        stack.push("b");
    
        System.out.println("Stack top element:"+stack.peek());
        System.out.println("Stack top element out of stack:"+stack.pop());
        System.out.println("Stack top element out of stack:"+stack.pop());
        System.out.println("Stack top element out of stack:"+stack.pop());
    }
}

Stack linked list implementation: when adding nodes, the top element of the stack is the newly added node, and the next of the node points to the previous node. When deleting elements, the current node points to the next node.

Code implementation:

/**
 * Stack Implementation of linked list
 * 
 * @Author (yequan17)
 * @Version (2021.12.7)
 */
public class JStackList
{
    //Linked list data structure
    static class Node<E> {
        Node<E> next = null;    
        E data;
        public Node(E data) {
        this.data = data;
        }
    }

    //Linked list implementation stack data structure
    static class ListNodeStack<E> {
        Node<E> top = null;

        boolean isEmpty() {
            return top == null;
        }

        public void push(E item) {
            Node<E> node = new Node<E>(item);
            node.next = top;
            top = node;
        }

        public E pop() {
            if (this.isEmpty()) return null;
            E data = top.data;
            top = top.next;
            return data;
        }

        public E peek() {
            if (this.isEmpty()) return null;
            return top.data;
        }
    }
    
    public static void main(String[] args) {
        ListNodeStack<Integer> stack = new ListNodeStack<>();
        System.out.println("Push ");
        stack.push(1);
        stack.push(2);
        System.out.println("Out of stack:"+stack.pop());
        System.out.println("Out of stack:"+stack.pop());
        System.out.println("Whether the stack is empty:"+stack.isEmpty());
    }   
    
}

summary

In actual use, we don't need to implement Stack ourselves. Java has completely encapsulated it for us. We can directly use Stack by introducing java.util.Stack.

A question to consider:
Why should the length of the array be 10 instead of other numbers when the array implements the stack? And how to expand it?

If we look at the Java source code of Stack, we will know that the real implementation of Stack is not a simple array, but the Vector class, which implements an extensible object array. Like arrays, it contains components that can be accessed using integer indexes. However, the size of the Vector can be increased or reduced as needed to accommodate adding and deleting items after the Vector is created.

The default capacity of Vector is 10, and its capacity expansion increment is twice the original capacity, that is, the capacity of Vector at the beginning is 10, and the capacity will become 20 at one time.

Topics: Java data structure Back-end