DestroyList是否存在问题?
来源:8-6 案例:单链表的基本实现

慕盖茨3428307
2025-01-30
老师,您好。
注意到您的DestroyList代码如下:
void DestroyList(ListNode **head) {
if (!head || !(*head)) return;
ListNode *current = *head;
while (current) {
ListNode *to_be_destroy = current;
current = current->next;
DestroyNode(&to_be_destroy);
}
*head = NULL;
}
您在讲课时,提到“需要将*head置为NULL,这样外部就知道链表已经被销毁了”。可是我观察DestroyNode的代码:
void DestroyNode(ListNode **node_ptr) {
(*node_ptr)->next = NULL;
free(*node_ptr);
*node_ptr = NULL;
}
其中*node_ptr = NULL;
已经在尝试做类似的事情了,理论上每个Node的指针都会置为Null。
于是我注释掉DestroyList中的*head = NULL;
,却发现链表似乎没有被成功删除,head仍然指向了一段地址。
我进一步分析后,发现问题可能出现在DestroyList的这一行代码中:
ListNode *to_be_destroy = current;
在这里发生了复制,这导致调用DestroyNode时,虽然to_be_destroy指向的内存被释放了,但是DestroyNode中的*node_ptr = NULL;
却失效了,因为真正置为NULL的是复制出来的、新的to_be_destroy指针,而非我们希望的指针。
最后,我做了如下修改,发现每个Node的指针都如设想的那样被置为Null了。
void DestroyList(ListNode **head) {
if (!(head) || !(*head))
return;
ListNode **current = head;
while (*current) {
ListNode **to_be_destroy = current;
current = &(*current)->next;
DeleteNode(to_be_destroy);
}
// *head = NULL;
}
请问我的分析和修改是否正确?
写回答
1回答
-
bennyhuo
2025-01-30
分析没问题,就这个案例来讲,修改的运行结果看上去也正确。
不过,实践中不建议这样处理,因为明显程序复杂了不少。这里的关键点在于链表(n个节点)和一个节点的表示形式相同导致,如果再进一步做抽象,把链表的类型也定义出来,就不会有这种疑问了。00
相似问题