问题描述
我在这个论坛上到处都是关于双向链表的实现,我无法理解下面的代码。
// 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”节点。
伪节点方法通常会导致代码更简洁,因为这样,所有实际节点将始终具有“上一个”节点,而所有实际节点将始终具有“下一个”节点。
这似乎是您的代码摘录中采用的方法。