实现双链表



我在这个论坛上浏览了关于双链表实现的内容,但我无法理解下面的代码。

// 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;
}
}
}

这是一个不太漂亮的建筑,但我认为这个解释符合你的情况。

给定一个列表(任何类型(,您至少需要知道如何到达第一个元素,以及如何判断何时看到最后一个元素。

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

对于链接列表,要知道列表的起始位置,可以对第一个节点进行简单引用,也可以有一个始终存在的完整"伪"节点。

要知道列表的结束位置,您可能有一个null的"next"引用,或者您可能有始终存在的完整"dummy"节点。

伪节点方法通常会产生更干净的代码,因为所有实际节点都将始终具有"上一个"节点,而所有实际节点将始终具有一个"下一个"结点。

这似乎就是您的代码提取中所采用的方法。

相关内容

  • 没有找到相关文章

最新更新