链表的头节点和起始节点有什么区别

What is the difference between the head node and starting node of link list?

本文关键字:节点 什么 区别 链表      更新时间:2023-10-16

链接列表中的头节点是否有任何信息,或者它只指向链接列表的第一个节点?
我们可以将头节点定义为链接列表的起始节点吗
头节点是否只指向第一个节点?链表由节点组成,每个节点都包含一些数据和到列表中另一个节点的链接。但是,第一个节点是包含数据和到第二个节点的链接的节点吗?或者它只包含到节点的链接(没有数据)?我认为链表中的第一个节点既有数据,也有到另一个节点的链接,但在一本介绍性的书中,它解释说头是一个节点,但却是一个链接,可以让你到达第一个节点。同时head是一个节点类型的变量。为什么是这样?

这取决于实现。head变量通常是指向列表中第一个节点的节点指针,例如在以下一个节点列表中:

        +--------+
head -> | node 1 | -> NULL
        +--------+

然而,我看到过这样的实现,其中"空"(双链接)列表由两个节点组成,因此插入和删除代码不必担心尝试在头之前或尾部之后插入,或删除头/尾部的边缘情况。

由于要插入的每个位置(以及允许删除的每个节点)都有一个prevnext节点,因此简化了代码。

        +-------+    +------+    +-------+
head -> | dummy | -> | node | -> | dummy | -> NULL
NULL <- |  node | <- |   1  | <- |  node | <- tail
        +-------+    +------+    +-------+

插入和删除不是对头部或尾部进行大量检查,而是:

def insertBefore (node, newnode):
    newnode.next = node
    newnode.prev = node.prev
    node.prev.next = newnode
    node.prev = newnode
def deleteNode (node):
    node.prev.next = node.next
    node.next.prev = node.prev
    free node

它稍微复杂了列表遍历,因为您必须从curr = head.next而不是curr = head开始,并在curr == last而不是curr == NULL结束,但有些人认为这是一种有效的权衡,代价是两个未使用的节点。

至少可以用三种不同的方法

  • 存储指向列表对象内部节点的指针
  • 有一个带有空数据成员的"head"节点
  • 有一个没有数据成员的特殊"头"节点

其中每一种都有利于某些操作或优化所用空间的折衷方案。

具有与其他节点相同类型的头对象简化了一些链接操作。具有没有数据有效载荷的头节点可以节省内存。将指针存储在列表对象中可能会为空列表节省动态分配,但会使swap更难实现。

没有一个绝对是最适合所有用途的。

通常,头节点是链表的第一个节点,但从"类型"的角度来看,它与任何其他节点都没有什么不同。它确实包含数据以及指向下一个节点(链表的第二个节点,如果存在的话)的指针。