需要头节点

时间:2010-11-17 06:49:53

标签: data-structures

我们说标题链表是由标记列表开头的称为标题节点的特殊节点组成的 但我不明白这个标题节点的重要性。 请帮帮我?

2 个答案:

答案 0 :(得分:2)

拥有哨兵节点可以防止您处理某些边缘情况。

最大的是空检查:您总是知道列表顶部会有一个节点,您可以在之后插入节点,因此您不必处理检查head是否为空。 (由于类似的原因,它也有助于建立尾节点)

考虑两种情况:

使用头部和尾部节点:

addNewDataAtHead( data ):
    newNode = new Node(data);
    newNode.next = head.next;
    newNode.prev = head;
    head.next.prev = newNode;
    head.next = newNode;

addNewDataAtHead( data ):
    newNode = new Node(data);
    if (head == null):
        head = newNode;
    newNode.next = head;
    head.prev = newNode;
    head =  newNode;

第一个的意图更加清晰,因为它就像插入其他地方一样。第二种情况要求您检查特殊情况。

答案 1 :(得分:1)

有一种链接列表,您可以大大简化附加,插入和删除代码,但需要花费一点存储空间,并且在遍历列表时可以节省额外的工作量。

那是因为空列表如下所示:

        +-------+    +-------+
head -> | dummy | -> | dummy | -> null
null <- | head  | <- | tail  | <- tail
        +-------+    +-------+

不是担心你是否追加(或插入)一个空列表,或者你的删除是否会创建一个空列表,而是更简单。

初始化变得稍微复杂一些,左边是原始的,右边是 all 下面的代码。这通常不会导致问题,因为列表创建发生一次但插入和删除发生了很多。

def init ():                            def init ():
    head = null                             head = new node
    tail = null                             tail = new node
                                            head->next = tail
                                            head->prev = null
                                            tail->prev = head
                                            tail->next = null

比较经典追加(插入更复杂,因为您可能需要在head之前插入,在中间插入,或在tail之后插入简化插图:

def append (node):                      def append (node):
    node->next = null                       node->next = tail
    if head == null:                        node->prev = tail->prev
        head = node                         tail->prev = node
        tail = node
        node->prev = null
    else:
        tail->next = node
        node->prev = tail
        tail = node

删除也大大简化,因为使用经典的链表,需要进行大量检查以确保不取消引用空指针:

def delete (node):                      def delete (node):
    if node == head and node == tail:       if node != head and node != tail:
        head = null                             node->prev->next = node->next
        tail = null                             node->next->prev = node->prev
    elsif node == head:                         free node
        head = head->next
        head->prev = null
    elsif node == tail:
        tail = tail->prev
        tail->next = null
    else:
        node->prev->next = node->next
        node->next->prev = node->prev
    free node

遍历列表的代码当然需要排除虚拟节点,但这是一个微不足道的变化:

def traverse (head):                    def traverse (head):
    node = head                             node = head->next
    while node != null:                     while node != tail:
        do something with node                  do something with node
        node = node->next                       node = node->next

我自己,我不是这样的代码的忠实粉丝,因为它可能表明人们懒得理解数据结构和算法是如何工作的。我宁愿拥有更复杂的代码,因为它显示了一个人可以思考问题的迹象。无论如何,这是你只倾向于写一次的东西。