[英]Implement doubly linked list
我在這個論壇上環顧四周關於雙向鏈表的實現,但我無法理解下面的代碼。
// 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, header, 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;
}
}
}
這是建築不是很漂亮,但我認為這個解釋符合你的情況。
給定一個列表(任何類型的),您至少需要知道如何到達第一個元素,以及如何判斷何時看到了最后一個元素。
有幾種方法可以滿足這些要求。
對於鏈表,要知道列表從哪里開始,您可能有對第一個節點的簡單引用,或者您可能有一個始終存在的完整“虛擬”節點。
要知道列表在哪里結束,您可能有一個空的“下一個”引用,或者您可能有一個始終存在的完整“虛擬”節點。
虛擬節點方法通常可以產生更清晰的代碼,因為所有實際節點將始終具有“上一個”節點,而所有實際節點將始終具有“下一個”節點。
這似乎是您的代碼提取中采用的方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.