C:如何释放链表中的节点?
Posted
技术标签:
【中文标题】C:如何释放链表中的节点?【英文标题】:C: How to free nodes in the linked list? 【发布时间】:2011-09-19 00:25:14 【问题描述】:如何释放在另一个函数中分配的节点?
struct node
int data;
struct node* next;
;
struct node* buildList()
struct node* head = NULL;
struct node* second = NULL;
struct node* third = NULL;
head = malloc(sizeof(struct node));
second = malloc(sizeof(struct node));
third = malloc(sizeof(struct node));
head->data = 1;
head->next = second;
second->data = 2;
second->next = third;
third->data = 3;
third->next = NULL;
return head;
我在main()中调用buildList函数
int main()
struct node* h = buildList();
printf("The second element is %d\n", h->next->data);
return 0;
我想释放头部、第二个和第三个变量。 谢谢。
更新:
int main()
struct node* h = buildList();
printf("The element is %d\n", h->next->data); //prints 2
//free(h->next->next);
//free(h->next);
free(h);
// struct node* h1 = buildList();
printf("The element is %d\n", h->next->data); //print 2 ?? why?
return 0;
两个打印 2. 不应该调用 free(h) 删除 h。如果是这样,为什么 h->next->data 可用,如果 h 是免费的。当然,“第二个”节点没有被释放。但是由于 head 被移除,它应该能够引用下一个元素。这里有什么错误?
【问题讨论】:
您是否在取消链接或释放它们时遇到问题?如果是后者,则使用来自malloc()
的返回值调用free()
。
user349433:这不是硬件,我尝试在 main 中使用 free(h)。那么如果 h 不存在,那么 h->next->data 怎么会给出值 2?于是我问。但是 free(h->next) 也应该被调用。但是既然h是头,去掉头后,我肯定不能引用头->下一个,不是吗。我哪里弄错了?
free()
不会擦除内存中的内容,它只是允许这些内容以后再使用。巧合的是,指针 h->next
仍然有效,因为您 free()
'd 的内存尚未被重用。
@jase21 Well Heath 回答了这个问题。它只是在您尝试时有效,但不能保证它在将来或在另一台机器上也能正常工作。在另一台机器上做h->next->data
可能会给你带来分段错误。好的,假设您有h
具有以下数据:h->next = 0x12341281; h->data = 1
,当您执行free(h)
时,您只需让机器知道将来malloc
您可以覆盖h
,h
不是更多地被您的程序使用。但是h->next = 0x12341281; h->data = 1
的数据似乎一直存在,这并不意味着您应该使用它们。
@jase21 也许在将来malloc
,其中h->next
和h->data
被保存,将写入其他内容。然后在执行h->next->data
时会出现分段错误。
【参考方案1】:
释放列表的迭代函数:
void freeList(struct node* head)
struct node* tmp;
while (head != NULL)
tmp = head;
head = head->next;
free(tmp);
函数的作用如下:
检查head
是否为NULL,如果是则列表为空,我们就返回
将head
保存在tmp
变量中,并使head
指向列表中的下一个节点(这在head = head->next
中完成
free(tmp)
变量,而head
只是指向列表的其余部分,返回步骤1
【讨论】:
只需确保在将列表头指针传递给此函数后将其设置为空即可。事实上,在释放节点之前将每个节点的每个 next 指针设置为 null 也是一个好主意。 @foobar 如果节点中的数据也是使用 malloc 创建的,我们是否必须在释放 temp 之前释放它?喜欢:免费(tmp->数据);免费(tmp); @Robert 是的!如果你先释放tmp
,那么 tmp->data 可能会指向垃圾,你会得到一个段错误。
也许最好在 FreeList 函数中直接通过引用传递头指针并将指针设为 NULL。所以,这将是 void freeList(struct node** head)blah;废话; *头=空;。这样可以避免 David 提到的问题。
你们都忽略了非 NULL 头指针根本不会中断循环。【参考方案2】:
只需遍历列表即可:
struct node *n = head;
while(n)
struct node *n1 = n;
n = n->next;
free(n1);
【讨论】:
【参考方案3】:一个函数就可以完成这项工作,
void free_list(node *pHead)
node *pNode = pHead, *pNext;
while (NULL != pNode)
pNext = pNode->next;
free(pNode);
pNode = pNext;
【讨论】:
【参考方案4】:struct node
int position;
char name[30];
struct node * next;
;
void free_list(node * list)
node* next_node;
printf("\n\n Freeing List: \n");
while(list != NULL)
next_node = list->next;
printf("clear mem for: %s",list->name);
free(list);
list = next_node;
printf("->");
【讨论】:
【参考方案5】:你总是可以像这样递归地做:
void freeList(struct node* currentNode)
if(currentNode->next) freeList(currentNode->next);
free(currentNode);
【讨论】:
argg,递归在纸面上很不错……但实际上,与像我或 jase21 这样的简单循环相比,它的内存和 CPU 需求非常昂贵。当您有 1328786 个节点时,展开堆栈并不便宜。 @elcuco 我同意。在问题提出的这种情况下,它会表现良好,但如果您正在查看那么大的列表,那么毫无疑问循环会让您处于更好的位置。 这在可以进行尾递归的语言中是可以的。那不是C 这段代码不是尾递归的。 (它在递归之后做某事)并且不能从尾递归优化中受益 我认为如果在 NULL 节点上调用此函数会导致错误。也许在定义的第一行放置一个 NULL 检查,而不是检查下一个节点是否为 null?以上是关于C:如何释放链表中的节点?的主要内容,如果未能解决你的问题,请参考以下文章