深入学习数据结构之栈(二)

  上一篇文章我们描述了什么是栈,以及Java中Stack的实现方式。

  先前介绍了栈有两种实现方式,一种是通过数组实现(可以参考Java的Stack),另外一种就是链表,今天我们手写一个通过链表实现栈的功能。

public class LinkStack<E> {

    private Node node;
    private int elementCount;

    // 初始化
    public LinkStack() {
        node = null;
        elementCount = 0;
    }

    // 添加元素到栈顶
    public E push(E item) {
        // 创建元素
        Node next = new Node(item);
        if (node == null) {
            node = next;
        } else {
            next.nextNode = node;
            node = next;
        }
        elementCount++;
        return item;
    }

    // 弹出栈顶元素
    public synchronized E pop() {
        if (node == null) {
            return null;
        }
        Node top = node;
        node = top.nextNode;
        top.nextNode = null;
        elementCount--;
        return top.data;
    }

    // 读取栈顶元素
    public synchronized E peek() {
        if (node == null) {
            return null;
        }
        Node top = node;
        return top.data;
    }

    // 判断栈是否为空
    public boolean empty() {
        return size() == 0;
    }

    // 读取栈大小
    public int size() {
        return elementCount;
    }

    // 清空栈数据
    public void clear() {
        node = null;
        elementCount = 0;
    }

    class Node {
        private E data;
        private Node nextNode;

        public Node(E data) {
            this.data = data;
        }

    }
}

实现逻辑:

  (一)结构:LinkStack使用内部对象保存我们需要保存的数据,以及指向下一个节点的指针。

  (二)添加:当栈为空时,创建节点,将栈顶指针指向新创建节点,更新计数器

        当栈不为空时,创建节点,将新创建的节点指向当前栈顶节点,同时将栈顶节点指针指向新创建节点。更新计数器

  (三)弹出:获取栈顶节点,同时将栈顶指针指向下一个节点,同时断开原栈顶节点和栈的关联关系。更新计数器

  (四)清除:将栈顶指针置为null,更新计数器

 

对比:

  数组实现:当数量超过数组大小时需要重新开辟新的数组,同时将原数组数据进行拷贝,一定程度上浪费了内存和性能,

    Java中Stack 的 使用了synchronized 线程安全机制,降低了程序性能。

  链表实现:通过指针实现,比较灵活。

  注:上面案例中没有增加线程安全考虑,仅仅只是实现了基础功能。

总结:

  Stack 继承了Vector ,实现方法上全部使用synchronized 关键字,而且使用数组实现,存在需要不断扩容问题。因此不推荐使用Stack,现在Java中可以使用Deque进行代替。

  

posted @ 2019-05-07 22:26  阿朗~  阅读(215)  评论(0)    收藏  举报