1.首先重写双向链表

public class DoubleLink<T> {
    public static class Node<T> {
        public T value;
        public Node<T> last;
        public Node<T> next;

        public Node(T data) {
            value = data;
        }
    }

    private Node<T> head;
    private Node<T> tail;

    public void addHead(T data) {
        Node<T> newNode = new Node<>(data);
        if (head == null) {
            head = newNode;
            tail = newNode;
        } else {
            newNode.next = head;
            head.last = newNode;
            head = newNode;
        }
    }

    public void addLast(T data) {
        Node<T> newNode = new Node<T>(data);
        if (head == null) { // 如果链表为空
            head = newNode; // 表头指针直接指向新节点
            tail = newNode;
        } else {
            tail.next = newNode; //last指向的节点指向新节点
            newNode.last = tail; //新节点的前驱指向last指针
            tail = newNode; // last指向新节点
        }
    }

    public T popFromHead() {
        if (head == null) {
            return null;
        }
        Node<T> cur = head;
        if (head == tail) {
            head = null;
            tail = null;
        } else {
            head = head.next;
            cur.next = null;
            head.last = null;
        }
        return cur.value;
    }


    public T popFromBottom() {
        if (head == null) {
            return null;
        }
        Node<T> cur = tail;
        if (head == tail) {
            head = null;
            tail = null;
        } else {
            tail = tail.last;
            tail.next = null;
            cur.last = null;
        }
        return cur.value;
    }

    public Node<T> reverseDoubleLink() {
        Node<T> pre = null;
        Node<T> next = null;
        while (head != null) {
            next = head.next;
            head.next = pre;
            head.last = next;
            pre = head;
            head = next;
        }
        this.head = pre;
        return pre;
    }

    public Node<T> remove(Integer num) {
        //删除头部为num的Node,可能不只是一个
        while (head != null) {
            if (head.value != num) {
                break;
            }
            head = head.next;
        }

        Node<T> pre = head;
        Node<T> cur = head;
        while (cur != null) {
            if (cur.value == num) {
                pre.next = cur.next;
            } else {
                pre = cur;
            }
            cur = cur.next;
        }
        return head;
    }

    public void print() {
        Node<T> cur = this.head;
        while (cur != null) {
            System.out.print(cur.value + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    public boolean isEmpty() {
        return head == null;
    }

}

2. 利用重写的双向链表来封装为Queue

public class MyQueue<T> {
    private DoubleLink<T> queue;

    public MyQueue() {
        queue = new DoubleLink<>();
    }

    public void push(T value) {
        queue.addHead(value);
    }

    public T poll() {
        return queue.popFromBottom();
    }

    public boolean isEmpty() {
        return queue.isEmpty();
    }
}

3.利用重写的双向链表来封装为Stack

public class MyStack<T> {
    private DoubleLink<T> stack;

    public MyStack() {
        stack = new DoubleLink<>();
    }

    public void push(T value) {
        stack.addHead(value);
    }

    public T poll() {
        return stack.popFromHead();
    }

    public boolean isEmpty() {
        return stack.isEmpty();
    }
}

hhhhh