我们是否需要循环链表中的头节点

时间:2018-02-19 05:26:21

标签: c pointers linked-list

我需要创建一个循环链表。但是,我不确定我是否应该拥有head节点。如果我包含head节点,我将能够轻松清空所有内容。但是最后一个元素必须指向head指向的节点?我不确定这是否可以缓解事情或使事情变得更难。

2 个答案:

答案 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。

例如,带有标记节点的空的双向链接循环列表如下所示:

enter image description here

前哨节点是持久性的,通常不承载任何有效载荷。添加节点后,列表开始如下所示:

enter image description here

如您所见,这允许按照插入节点的顺序(使用next指针)或反向(使用prev指针)遍历列表。

同样,对于单链表,如果需要插入顺序,那么使列表循环从一开始就失败了目的。如果不需要插入顺序,那么你必须随身携带一个标记节点是没有意义的,因为你永远不会使用它。任何旧节点都可以。