算法通关村第四关——如何基于数组和链表实现栈

159 阅读2分钟

1.基于数组实现栈

首先要明确,栈的常用方法有哪些?

  1. isEmpty(); 判断栈是否为空
  2. size(); 栈的大小;
  3. push(T ele); 元素入栈;
  4. pop(); 元素出栈;
  5. peek(); 查看栈顶元素,但栈顶元素不出栈;

代码实现:

/*
 * 基于数组手写栈
 * */
public class MyStack<T> {

    // 数组
    private Object[] stack;

    // 栈顶位置,也可以理解为栈的大小;
    private int top;

    private final double threshold = 0.8;

    public MyStack() {
        stack = new Object[10];
    }

    // 判断栈中元素是否为空
    public boolean isEmpty() {
        return top == 0;
    }

    // 元素入栈
    public void push(Object ele) {
        if (top < stack.length) {
            stack[top++] = ele;
        }
        // 如果达到扩容阈值,就对数组扩容
        if (top >= stack.length * threshold) {
            expandCapacity();
        }
    }

    // 查看栈顶元素
    public T peek() {
        T ele = null;
        if (top > 0) {
            ele = (T) stack[top - 1];
        }
        return ele;
    }

    // 元素出栈
    public T pop() {
        T ele = peek();
        // 如果top > 0 说明栈中还有元素
        if (top > 0) {
            stack[top - 1] = null;
            top--;
        }
        return ele;
    }

    // 数组扩容
    private void expandCapacity() {
        int len = stack.length * 3 / 2;
        stack = Arrays.copyOf(stack, len);
    }

    // 查看当前栈中的元素总个数
    public int size() {
        return top;
    }

    // 使用Main方法测试
    public static void main(String[] args) {
        MyStack<Integer> stack = new MyStack<>();
        for (int i = 0; i < 10; i++) {
            stack.push(i);
        }
        stack.push(11);
        stack.push(12);
        stack.push(13);
        stack.push(14);
        int size = stack.size();
        int res=stack.peek();
        int res=stack.pop();
        size=stack.size();
    }

}

4.基于链表实现栈

先解释一下,这里我为什么要维持一个头节点head ;

首先元素入栈时是这样的:

当待入栈元素是这样的:1,2,3,4,5;

此时形成的链表结构为:

image.png

此是我们插入元素时,只要进行尾插法即可;但是删除元素时,需要依靠头节点,遍历到tempNode节点的上一个位置,也就是图中的 4 位置,记作curNode,然后删除tempNode,再将curNode赋值给tempNode即可;

还有一种可以形成的链表结构:

每次插入时将新的节点插入到链表的头部,这样元素在出栈时就不用在做过多的处理,直接head=head.next;即可

如图:

image.png

我是用的第一种实现,仅供参考;
代码如下:

/*
 * 基于链表手写栈
 * */
public class LinkedStack<T> {
    // 定义链表结构
    static class LinkedList<T> {
        T val;
        LinkedList<T> next;

        public LinkedList(T val) {
            this.val = val;
        }
    }

    // 定义头节点
    private LinkedList<T> head;
    // 栈顶元素
    private LinkedList<T> tempNode;
    // 栈的大小
    private int size;

    // 初始化链表结构
    public LinkedStack() {
        head = new LinkedList(-1);
        tempNode = head;
    }

    // 元素入栈
    public void push(T ele) {
        tempNode.next = new LinkedList<T>(ele);
        tempNode = tempNode.next;
        size++;
    }
    // 判断栈为空
    public boolean isEmpty() {
        return size == 0;
    }
    // 查看栈顶元素
    public T peek() {
        T ele = null;
        if (head.next != null) {
            ele = tempNode.val;
        }
        return ele;
    }

    // 元素出栈
    public T pop() {
        T ele = peek();
        if (ele != null) {
            LinkedList<T> curNode = head.next;
            while (curNode.next.val != ele) {
                curNode = curNode.next;
            }
            LinkedList<T> next = curNode.next;
            curNode.next = next.next;
            // 因为原来栈顶元素已经出栈,所以需要维持一个新的栈顶元素,也就是curNode;
            tempNode = curNode;
            size--;
        }
        return ele;
    }
    // 栈的大小
    public int size() {
        return size;
    }

    // 使用Main方法测试
    public static void main(String[] args) {
        LinkedStack<String> stack = new LinkedStack();
        for (int i = 0; i < 10; i++) {
            stack.push(i + "");
        }
        int size = stack.size();
        String val = stack.pop();
        size = stack.size();
    }

}