实现双向链表

问题描述

在这个论坛上到处都是关于双向链表的实现,我无法理解下面的代码

// instance variables of the DoublyLinkedList
    private final Node<E> header;     // header sentinel
    private final Node<E> trailer;    // trailer sentinel
    private int size = 0;       // number of elements in the list
    private int modCount = 0;   // number of modifications to the list (adds or removes)

    /**
     * Creates both elements which act as sentinels
     */
    public DoublyLinkedList() {

        header = new Node<>(null,null,null);      // create header
        trailer = new Node<>(null,header,null);   // trailer is preceded by header
        header.setNext(trailer);                    // header is followed by trailer
    }

我看过有关链接列表和双重列表的视频,但是我没有看到这种实现。背后的逻辑是什么,例如:trailer = new Node<>(null,null)

解决方法

您可能有一些DoubleLinkedList,例如:

     /**
     * A double linked list.
     *
     */
    public class DoubleLinkedList<E> {
    
        private final Node<E> header;     // header sentinel
        private final Node<E> trailer;    // trailer sentinel
        private int size = 0;       // number of elements in the list
        private int modCount = 0;   // number of modifications to the list (adds or removes)
    
        public DoubleLinkedList() {
            this.header = new Node<>(
                        // The successor of the header is the trailer.
                        // It will be set with: header.setNext(trailer);
                    null,// The predecessor of the header is always null,// because there there is no node before the first
                    null,// The payload of the node is null.
                        // I guess it is just a part of the example.
                    null
            );
    
            this.trailer = new Node<>(
                    // The successor of the trailer is always null,// because there there is no node after the last
                    null,// The predecessor of the trailer is the header
                    // at construction of this object
                    header,// The payload of the node is null.
                    // I guess it is just a part of the example.
                    null
            );
            // Now is the successor of the header set to the trailer.
            header.setNext(trailer);
        }
    
        // Some list methods like add,remove,get,...
    
    
        /**
         * The nodes of the List
         *
         * @param <T> The type of the stored objects in the list.
         */
        static class Node<T> {
    
            /**
             * The predecessor of this node.
             */
            private Node<T> predecessor;
    
            /**
             * The successor of this node.
             */
            private Node<T> successor;
    
            /**
             * The payload
             */
            private final T payload;
    
            public Node(final Node<T> successor,final Node<T> predecessor,final T payload) {
                this.predecessor = successor;
                this.successor = successor;
                this.payload = payload;
            }
    
            // Getter and Setter:
    
            private Node<T> getPredecessor() {
                return this.predecessor;
            }
    
            private void setNext(final Node<T> next) {
                this.predecessor = next;
            }
    
            private Node<T> getSuccessor() {
                return this.successor;
            }
    
            private void setPrevious(final Node<T> previous) {
                this.successor = previous;
            }
    
            private T getPayload() {
                return this.payload;
            }
        }
    }

这不是很漂亮的建筑,但是我认为这种解释与您的情况相符。

,

给出一个列表(任何形式),您至少需要知道如何到达第一个元素,以及如何知道何时看到了最后一个元素。

有几种方法可以满足这些要求。

对于链接列表,要知道列表从何处开始,您可能对第一个节点有简单的引用,或者您可能有一个始终存在的完整“虚拟”节点。

要知道列表在何处结束,您可能有一个空的“ next”引用,或者您有一个始终存在的完整“ dummy”节点。

伪节点方法通常会导致代码更简洁,因为这样,所有实际节点将始终具有“上一个”节点,而所有实际节点将始终具有“下一个”节点。

这似乎是您的代码摘录中采用的方法。