5

这是我删除链表的功能:

void deleteList( NODE* head )
{
    NODE* temp1; 
    NODE* tempNext;
    temp1 = head;
    tempNext = NULL;

    while( temp1 != NULL )
    {
        tempNext = temp1->next;
        free(temp1);
        temp1 = tempNext;
    }
}

所以 temp1 首先指向头指针指向的位置。如果不是NULL,tempNext将被设置为指向列表的下一个元素。然后第一个元素 ( temp1) 被释放,并被temp1重新分配以指向tempNext指向的位置并重复过程。

这是删除整个列表的正确方法吗?

我问这个是因为当我使用此功能后打印列表时,它仍然会打印列表。而 IIRC 释放某些东西并不会删除它,只会将其标记为可用,所以我不确定如何判断这是否正确。

4

4 回答 4

7

您的代码看起来正确。

您也正确,释放列表的元素不会立即更改它们指向的内存。它只是将内存返回给将来可能重新分配的堆管理器。

如果您想确保客户端代码不会继续使用已释放列表,您可以将deleteListNODE指针也更改为 NULL:

void deleteList( NODE** head )
{
    NODE* temp1 = *head;
    /* your code as before */
    *head = NULL;
}
于 2012-12-17T16:00:36.103 回答
1

它仍然打印列表,因为您可能在调用此函数后没有设置head指针。NULL

于 2012-12-17T16:01:37.260 回答
1

I ask this because when I print the list after using this function, it still prints the list.

free使用指针和使指针无效是有区别的。如果free您拥有整个链表和头部,则意味着您不再“拥有”head所有next指针指向的位置的内存。因此,您无法保证那里会有什么值,或者内存是否有效。

但是,如果您在释放链接列表后不碰任何东西,您仍然可以遍历它并打印值的可能性非常大。

struct node{
    int i;
    struct node * next;
};

...
struct node * head = NULL;
head = malloc(sizeof(struct node));
head->i = 5;
head->next = NULL;
free(head);
printf("%d\n", head->i); // The odds are pretty good you'll see "5" here

您应该始终释放指针,然后直接将其设置为 NULL,因为在上面的代码中,注释为真。对调用后如何反应/包含做出任何假设也是危险的。headfree()

于 2012-12-17T16:12:09.273 回答
0

这是一个相当古老的问题,但也许它会帮助某人对该主题进行搜索。

这是我最近写的完全删除单链表的内容。我看到很多人对涉及大型列表的递归算法感到心痛,因为担心堆栈空间不足。所以这里是一个迭代版本。

只需传入“head”指针,该函数会处理其余的...

struct Node {
    int i;
    struct Node *next;

};

void DeleteList(struct Node *Head) {

    struct Node *p_ptr;

    p_ptr = Head;

    while (p_ptr->next != NULL) {
            p_ptr = p_ptr->next;
            Head->next = p_ptr->next;
            free(p_ptr);
            p_ptr = Head;
    }

    free(p_ptr);

}

于 2016-06-14T17:40:16.287 回答