链表实现中的虚拟节点

时间:2019-04-06 15:18:37

标签: c data-structures linked-list singly-linked-list

我正在尝试实现单链接列表。

要求是: 1.按数据顺序插入 2.从头部移开

我的实现中是否需要一个虚拟节点? 还应该将虚拟节点放置在列表的开头还是列表的结尾?

我用谷歌搜索了答案,发现虚拟节点在删除列表中的最后一个节点时很有帮助。但是,我不知道如何。 有人可以解释吗?

2 个答案:

答案 0 :(得分:1)

不需要虚拟节点来实现单链列表。它们可以用作定义不同于列表元素结构的列表结构的替代方法。

鉴于您的要求,您应该定义一个列表结构,该结构包含指向列表开头的指针和指向列表结尾的指针。这将使两个操作(在末尾插入和从头部移出)保持恒定的时间。

当列表为空时,必须小心以正确维护这些指针。

这是一个简单的例子:

struct list_elem_s {
    struct list_elem_s *next;
    int data;
    //... other payload fields
};

struct list_s {
    struct list_elem_s *head;
    struct list_elem_s *tail;
};

// initialize a list as empty
void list_initialize(struct list_s *list) {
    list->head = list->tail = NULL;
}

// free all elements from a list
void list_delete(struct list_s *list,
                 void (*free_node)(struct list_elem_s *node)) {
    struct list_elem_s *node;
    while ((node = list->head) != NULL) {
        list->head = node->next;
        node->next = NULL;
        if (free_node)
            free_node(node);
    }
    list->tail = NULL;
}

// add a node at the tail
void list_push(struct list_s *list, struct list_elem *node) {
    node->next = NULL;
    if (list->tail) {
        list->tail->next = node;
    } else {
        list->head = node;
    }
    list->tail = node;
}

// remove a node at the head
struct list_elem *list_pop_head(struct list_s *list) {
    struct list_elem_s *node;
    if ((node = list->head) != NULL) {
        if ((list->head = node->next) == NULL)
            list->tail = NULL;
    }
    return node;
}

答案 1 :(得分:1)

链接列表如下:

struct list_node {
    struct list_node *next;
    void *data;
};

struct list_node *head;

您永远不需要C中的链接列表中的虚拟节点。

虚拟节点用于允许以不提供指向指针的语言的单链接列表实现“删除当前”操作。就是这样。

当您有一个指向节点的指针时,可以通过将下一个节点移到该节点的顶部并释放下一个节点来删除该节点。虚拟节点确保始终有一个下一个节点来执行此操作。

但是在C语言中,最好保留指向下一个节点的指针,以便更好地为您服务。在迭代开始时,它是指向head的指针;在开始之后,这是一个指针list_node::next,其中list_node是先前查看的节点。