java - 使用双向链表的哨兵方法

标签 java linked-list doubly-linked-list

我正在浏览Java中的双向链表,我正在阅读Book中关于双向链表中的哨兵的内容。 。其中指出

In order to avoid some special cases when operating near the boundaries of a doubly-linked list, it helps to add special nodes at both ends of the list: a header node at the beginning of the list, and a trailer node at the end of the list. These “dummy” nodes are known as sentinels (or guards), and they do not store elements of the primary sequence

那些特殊情况是什么?为什么我们需要哨兵方法?是强制性的吗?如果我们对双链表使用常规方法(没有哨兵),这不是可以节省这些额外节点的内存吗?当以这种方式使用循环方法创建双链表时,我们必须删除哨兵吗?

最佳答案

维基百科注释中简要提到使用哨兵节点来简化链表的实现。

哨兵节点是位于列表前面的虚拟节点。

在双向链表中,哨兵节点指向链表的第一个和最后一个元素。我们不再需要为列表的头和尾保留单独的指针,就像我们对单链表所做的那样。

我们也不必担心更新头指针和尾指针,因为正如我们将看到的,如果我们在哨兵节点之后插入,从而在列表中添加一个项目,或者在哨兵节点之前插入,这种情况会自动发生,因此将一个项目添加到列表中。

我们可以消除用于单链表的容器对象,因为哨兵节点可以跟踪列表中的第一个和最后一个元素。如果我们这样做,那么我们将向用户返回一个指向哨兵节点的指针。

但是,数据结构一般都会设计有一个容器对象,它介导数据结构的使用者和数据结构的实现之间的通信,所以我们会保留容器对象。

@6502 在 How does a sentinel node offer benefits over NULL? 上的回答非常有帮助。

下面是节点双向链表中删除节点的代码,其中使用 NULL 来标记链表的结束,并使用两个指针first和last来保存第一个和最后一个节点的地址:

// Using NULL and pointers for first and last
if (n->prev) n->prev->next = n->next;
        else first = n->next;
if (n->next) n->next->prev = n->prev;
        else last = n->prev;

这是相同的代码,其中有一个特殊的虚拟节点来标记列表的末尾,并且列表中第一个节点的地址存储在特殊节点的下一个字段中,最后一个节点在该列表存储在特殊虚拟节点的 prev 字段中:

// Using the dummy node
n->prev->next = n->next;
n->next->prev = n->prev;

节点插入也有同样的简化;例如,要在节点 x 之前插入节点 n(x == NULL 或 x == &dummy 表示在最后位置插入),代码将是:

// Using NULL and pointers for first and last

n->next = x;
n->prev = x ? x->prev : last;
if (n->prev) n->prev->next = n;
        else first = n;
if (n->next) n->next->prev = n;
        else last = n;

// Using the dummy node
n->next = x;
n->prev = x->prev;
n->next->prev = n;
n->prev->next = n;

正如您所看到的,对于双向链表,所有特殊情况和所有条件都删除了虚拟节点方法。

关于java - 使用双向链表的哨兵方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58049478/

相关文章:

java - jetty 配置错误

java - javax StreamSource 的目的是什么

Java图像显示问题

c++ - 插入到排序位置链表

c++ - 如何在循环双向链表中使用指针

java - 使用 BFS 构建迷宫?

C++出队问题......出队重复返回相同的元素

java - Java 链表

c - 在C中的双向链表中删除头节点的问题

c++ - 使用数据结构的日历和待办事项列表