我需要创建一个循环链表。但是,我不确定我是否应该拥有head
节点。如果我包含head
节点,我将能够轻松清空所有内容。但是最后一个元素必须指向head
指向的节点?我不确定这是否可以缓解事情或使事情变得更难。
答案 0 :(得分:4)
循环链表不需要 head 节点,因为它实际上没有头。它 然后需要一个指向列表中某些节点的指针,这样你就可以到达所有元素。
在释放列表方面,正常列表扫描将在处理指向null
的节点后停止。循环列表非常相似,只是您记住了您开始的节点,因此您可以在释放指向该节点的节点后停止。这种野兽的伪代码看起来像:
def deleteAll(someNode by reference):
# Do nothing for empty list.
if someNode == null:
return
# Process each node, stopping after one that points to start node.
nodeToDelete = someNode
do:
nextNode = nodeToDelete.next
free nodeToDelete
nodeToDelete = nextNode
until nodeToDelete == someNode
# Mark list as empty.
someNode = null
答案 1 :(得分:1)
对于循环链表,头节点(在这种情况下通常称为 sentinel 节点)仅在您需要跟踪元素的插入顺序时才有用,因为要维护一个订单,你需要知道起点。
对于单链接列表,这通常不是一个考虑因素,因为如果插入顺序很重要,那么首先使列表循环没有任何意义。但是,对于双向链接的列表,它变得有用,因为这样你就可以在任何一个方向上遍历一个列表:LIFO或FIFO。
例如,带有标记节点的空的双向链接循环列表如下所示:
前哨节点是持久性的,通常不承载任何有效载荷。添加节点后,列表开始如下所示:
如您所见,这允许按照插入节点的顺序(使用next
指针)或反向(使用prev
指针)遍历列表。
同样,对于单链表,如果需要插入顺序,那么使列表循环从一开始就失败了目的。如果不需要插入顺序,那么你必须随身携带一个标记节点是没有意义的,因为你永远不会使用它。任何旧节点都可以。