Java基于链表的栈和队列

上篇博客和大家分享了java的链表实现,这篇博客将和大家一起分享基于链表的栈和队列。这里可以先回忆一下基于动态数组实现的栈和队列,无论是底层是链表还是动态数组,栈和队列的接口都是一致的。

首先,我们一起来看以前定义的栈的接口

public interface StackInterface<E> {

    E pop();

    E peek();

    void push(E e);

    boolean isEmpty();

    int getSize();
}

相信大家一定不陌生,接下来,让我们一起看看如何使用链表实现栈,由于我们在链表中已经封装好一些方法,所以实现栈其实是很简单的

public class LinkedListStack<E> implements StackInterface<E> {

    private LinkedList<E> list;

    public LinkedListStack() {
        list = new LinkedList<>();
    }

    @Override
    public E pop() {
        return list.removeFirst();
    }

    @Override
    public E peek() {
        return list.getFist();
    }

    @Override
    public void push(E e) {
        list.addFirst(e);
    }

    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }

    @Override
    public int getSize() {
        return list.getSize();
    }

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append("Stack: top ");
        res.append(list);
        return res.toString();
    }
}

既然基于链表的栈已经被轻松拿下,那么队列一定也不会难住我们,我们还是先看以前定义好的队列的接口

public interface QueueInterface<E> {

    int getSize();

    boolean isEmpty();

    void enqueue(E e);

    E dequeue();

    E getFront();
}

同样根据队列的定义,使用我们在链表里封住好的方法

public class LinkedListQueue<E> implements QueueInterface<E> {

    private class Node {
        public E e;
        public Node next;

        public Node(E e, Node next) {
            this.e = e;
            this.next = next;
        }

        public Node(E e) {
            this(e, null);
        }

        public Node() {
            this(null, null);
        }

        @Override
        public String toString() {
            return e.toString();
        }
    }

    private Node head, tail;
    private int size;

    public LinkedListQueue() {
        head = null;
        tail = null;
        size = 0;
    }

    @Override
    public int getSize() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public void enqueue(E e) {
        if (tail == null) {
            tail = new Node(e);
            head = tail;
        } else {
            tail.next = new Node(e);
            tail = tail.next;
        }
        size++;
    }

    @Override
    public E dequeue() {
        if (isEmpty()) {
            throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
        }

        Node retNode = head;
        head = head.next;
        retNode.next = null;
        if (head == null) {
            tail = null;
        }
        size--;
        return retNode.e;
    }

    @Override
    public E getFront() {
        if (isEmpty()) {
            throw new IllegalArgumentException("Cannot dequeue from an empty queue.");
        }
        return head.e;
    }

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();

        Node cur = head;
        while (cur != null) {
            res.append(cur + "->");
            cur = cur.next;
        }

        res.append("NULL tail");
        return res.toString();
    }
}

这里需要注意的是,我们在链表的尾部添加了一个tail节点,因为队列是先进先出的结构,不同于栈,我们只需要操作头节点就可以了,在入队操作时,如果没有队尾的引用,那么每次都需要遍历整个链表,是O(n)的复杂度,所以引入了tail节点。

到了这里,同学们对于线性数据结构,应该会有一些新的认识,但是只有线性结构,往往是不够的,下一篇博客,将和大家一起分享一种新的数据结构,树结构。感谢阅读~

还请需要转载的同学注明出处:https://blog.csdn.net/sinat_33150417/article/details/82492809

猜你喜欢

转载自blog.csdn.net/sinat_33150417/article/details/82492809
今日推荐