链表的头节点和起始节点有什么区别
What is the difference between the head node and starting node of link list?
链接列表中的头节点是否有任何信息,或者它只指向链接列表的第一个节点?
我们可以将头节点定义为链接列表的起始节点吗
头节点是否只指向第一个节点?链表由节点组成,每个节点都包含一些数据和到列表中另一个节点的链接。但是,第一个节点是包含数据和到第二个节点的链接的节点吗?或者它只包含到节点的链接(没有数据)?我认为链表中的第一个节点既有数据,也有到另一个节点的链接,但在一本介绍性的书中,它解释说头是一个节点,但却是一个链接,可以让你到达第一个节点。同时head是一个节点类型的变量。为什么是这样?
这取决于实现。head
变量通常是指向列表中第一个节点的节点指针,例如在以下一个节点列表中:
+--------+
head -> | node 1 | -> NULL
+--------+
然而,我看到过这样的实现,其中"空"(双链接)列表由两个节点组成,因此插入和删除代码不必担心尝试在头之前或尾部之后插入,或删除头/尾部的边缘情况。
由于要插入的每个位置(以及允许删除的每个节点)都有一个prev
和next
节点,因此简化了代码。
+-------+ +------+ +-------+
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
更难实现。
没有一个绝对是最适合所有用途的。
通常,头节点是链表的第一个节点,但从"类型"的角度来看,它与任何其他节点都没有什么不同。它确实包含数据以及指向下一个节点(链表的第二个节点,如果存在的话)的指针。
- 比较两个节点坐标的最佳方法是什么?
- 在 c++ 中,在链表节点上使用括号有什么意义?
- 结构之外的节点 * head 有什么作用?
- 创建静态哨兵节点的正确方法是什么
- 函数调用中的结构节点* 和节点* 有什么区别?
- 光标和节点的AST遍历之间有什么区别
- 在链表中删除该节点时,Node* 接下来会发生什么情况
- 使用 CDT 从头文件中获取属性定义的节点元素是什么
- 链接列表C 类,这两个添加节点实现之间的差异是什么?
- 使用 typedef 创建节点有什么优势?
- 什么是左节点和右节点,其中节点可能> 2
- 在图算法中,确定是否访问节点的最佳方法是什么?
- 二叉搜索树节点的结构应该是什么
- 从节点数组和边缘向量获取所有子树的最有效方法是什么
- 在循环双向链表的第一个节点之前/之后插入的算法是什么?
- 为这个二进制节点类创建析构函数的正确方法是什么
- 链表的头节点和起始节点有什么区别
- 从使用链表实现的队列中弹出最大节点的最有效方法是什么?C++
- 有什么方法可以在 tbb::flow::graph 中的节点之间发送"heavy"类型?
- 在窗口的情况下,索引节点是什么?