Java's sequential stack and chained stack

Definition of stack

A stack is a linear list that restricts insertion and deletion operations to a section of the table. Usually, one end of the insertion and deletion can be called the top of the stack, and the exception end is called the bottom of the stack. When there are no elements in the table, it is called an empty stack.

Usually deletion (also known as "popping") is called a pop popoperation, and each deletion is the latest element on the top of the stack; each insertion (also known as "pushing") is called a push pushoperation.

When the stack is full, the push operation is performed, 上溢and when the stack is empty, the pop operation is called 下溢.

Overflow is an error condition, and underflow may be a normal case handling.

The operation of the stack is based on the principle of last in, first out, referred to as LIFO.

The basic operation definition of stack:

  • initStack: constructs an empty stack;
  • stackEmpty: determine whether it is empty;
  • stackFUll: determine whether the stack is full;
  • push: push the stack, push the element to the top of the stack;
  • pop: pop off the stack, pop the top element of the stack, pay attention to the non-empty judgment;
  • stackTop: Remove the top element of the stack without changing the pointer.

Make a simple Stack interface:

package com.wuwii.utils;

/**
 * 堆栈
 * @author Zhang Kai
 * @version 1.0
 * @since <pre>2017/12/14 22:51</pre>
 */
public interface Stack<E> {
    /**
     * 进栈
     *
     * @param element 进栈的元素
     */
    void push(E element);

    /**
     * 弹出栈顶元素 ,并改变指针
     *
     * @return 栈顶元素
     */
    E pop();

    /**
     * 返回栈顶元素 ,不改变指针
     *
     * @return 栈顶元素
     */
    E topElement();

    /**
     * 判断是否为空栈
     *
     * @return true为空栈
     */
    Boolean isEmpty();

    /**
     * 清空栈
     */
    void clear();

}

sequential stack

It is a sequential linear table that conforms to the LIFO operation rules.

package com.wuwii.utils;

/**
 * 顺序栈
 * @author Zhang Kai
 * @version 1.0
 * @since <pre>2017/12/14 23:05</pre>
 */
public class ArrayStack<E> implements Stack<E> {
    /**
     * 初始化栈的默认大小
     */
    private final int defaultSize = 10;
    /**
     * 栈的集合大小
     */
    private int size;
    /**
     * 栈顶的位置
     */
    private int top;
    /**
     * 元素存储在数组
     */
    private Object[] elements;

    /**
     * 初始化默认大小为10 的栈
     */
    public ArrayStack() {
        initStack(defaultSize);
    }

    /**
     * 初始化指定大小的栈
     * @param givenSize 指定栈大小
     */
    public ArrayStack(Integer givenSize) {
        initStack(givenSize);
    }

    /**
     * 初始化栈
     * @param givenSize 给定的栈大小
     */
    private void initStack(Integer givenSize) {
        size = givenSize;
        top = 0;
        elements = new Object[size];
    }

    /**
     * 清空栈
     */
    @Override
    public void clear() {
        top = 0;
    }

    /**
     * 进栈
     * @param element 进栈的元素
     */
    @Override
    public void push(E element) {
        sizeCheckForPush();
        elements[top++] = element;
    }

    /**
     * 弹出栈顶元素 ,并改变指针
     * @return 栈顶元素
     */
    @Override
    public E pop() {
        sizeCheckForPop();
        return (E) elements[--top];
    }
    /**
     * 返回栈顶元素 ,不改变指针
     * @return 栈顶元素
     */
    @Override
    public E topElement() {
        sizeCheckForPush();
        return (E) elements[top - 1];
    }

    /**
     * 判断是否为空栈
     * @return true为空栈
     */
    @Override
    public Boolean isEmpty() {
        return size == 0;
    }
    
    /**
     * 在进栈的时候检查
     */
    private void sizeCheckForPush() {
        if (top >= size) {
            throw new RuntimeException("Stack overflow");
        }
    }

    /**
     * 退栈检查
     */
    private void sizeCheckForPop() {
        if (isEmpty()) {
            throw new RuntimeException("Stack is empty");
        }
    }
}

chain stack

A linked linear table that conforms to the LIFO operation rules.

package com.wuwii.utils;


/**
 * @author Zhang Kai
 * @version 1.0
 * @since <pre>2017/12/15 12:58</pre>
 */
public class LinkStack<E> implements Stack<E> {
    /**
     * 链式单元
     */
    private Node<E> top;

    /**
     * 初始化链式堆栈
     */
    public LinkStack() {
        initStack();
    }

    /**
     * 初始化
     */
    private void initStack() {
        top = null;
    }

    /**
     * 存储单元
     */
    private static class Node<E> {
        E element;
        Node<E> next;
        Node(E element, Node<E> next) {
            this.element = element;
            this.next = next;
        }
    }
    /**
     * 进栈
     *
     * @param element 进栈的元素
     */
    @Override
    public void push(E element) {
        top = new Node<E>(element, top);
    }

    /**
     * 弹出栈顶元素 ,并改变指针
     *
     * @return 栈顶元素
     */
    @Override
    public E pop() {
        checkEmpty();
        E element = top.element;
        top = top.next;
        return element;
    }

    /**
     * 返回栈顶元素 ,不改变指针
     *
     * @return 栈顶元素
     */
    @Override
    public E topElement() {
        checkEmpty();
        return top.element;
    }

    /**
     * 判断是否为空栈
     *
     * @return true为空栈
     */
    @Override
    public Boolean isEmpty() {
        return top == null;
    }

    /**
     * 清空栈
     */
    @Override
    public void clear() {
        if (isEmpty()) {
            return;
        }
        for (Node<E> x = top; x != null; ) {
            Node<E> next = x.next;
            x.element = null;
            x.next = null;
            x = next;
        }
        size = 0;
    }

    /**
     * 检查链式堆栈是否为空,为空抛出异常
     */
    private void checkEmpty() {
        if (isEmpty()) {
            throw new RuntimeException("LinkStack is empty");
        }
    }
}

First, push modifies the next field of the newly generated linked list node and points to the top of the stack, then sets top to point to the new linked list node, and pop is the opposite.

Comparing sequential and chained stacks

The operation of implementing chain stack and sequential stack requires constant time, and the time complexity is O(1), mainly considering the space and time complexity.

When the sequential stack is initialized, a specified size must be given. When the stack is not full, it will cause a part of the waste of space. The chain stack becomes longer, which saves space relatively, but increases the pointer field and increases the overhead of the data structure.

When multiple stacks are required to be shared, the unidirectional extension of the sequential stack can be fully utilized in sequential storage, an array can be stored in two stacks, and each stack extends from the top of its own stack, thus reducing the waste of space . But it can only be used if the two have opposite requirements for stack space. It is best that one stack can only be increased, and one can only be decreased. If the two are added together, it may cause stack overflow.

If the space is shared among multiple sequential stacks, one stack is full, and the others may not be full. You need to use the LIFO algorithm of the stack to translate the full stack elements to the left or right, which will cause a large number of data elements to move, making The time cost increases.

Relatively speaking, using two stacks to share a space is a more suitable storage method, but it also increases the risk of stack overflow.

Due to the discontinuity of the chained storage structure, when it is needed, it can be stored whenever it is needed. There is no overflow problem, but the overhead of the structure is increased, which is a waste of space in general, but does not require stack sharing.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325208536&siteId=291194637