它看起来没有重复的问题......所以我想要一个函数来释放单个链表中的所有节点,我想以递归方式进行。我想出了一个我觉得它会起作用的关闭,但事实并非如此。似乎在删除了一个节点之后,上层堆栈函数将不会以递归方式为借口。我想知道如何修改代码以使其工作。
#include <stdlib.h>
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int data;
struct Node *next;
};
void ft_list_clear(struct Node *begin_list)
{
if ((begin_list->next))
ft_list_clear(begin_list->next);
if(!(begin_list->next))
{
free(begin_list);
begin_list = NULL;
}
}
int main()
{
struct Node* head = NULL;
struct Node* second = NULL;
struct Node* third = NULL;
// allocate 3 nodes in the heap
head = (struct Node*)malloc(sizeof(struct Node));
second = (struct Node*)malloc(sizeof(struct Node));
third = (struct Node*)malloc(sizeof(struct Node));
head->data = 1; //assign data in first node
head->next = second; // Link first node with second
second->data = 2; //assign data to second node
second->next = third;
third->data = 3; //assign data to third node
third->next = NULL;
ft_list_clear(head);
return 0;
}
答案 0 :(得分:3)
你非常接近
col-md-4
解释代码
第一个void ft_list_clear(struct Nude *list)
{
if (!list) { return; }
ft_list_clear(list->next);
list->next = null;
free(list);
}
检查列表当前是否为if
,如果是,则退出递归。
如果列表不是null
递归调用该函数。
这将重复到列表null
的末尾。
然后由于null
已被递归调用清除,您可以在此调用中将其设置为next
(因为这会清除所有内容,因此不是必需的)。
最后实际上null
此节点在返回上一个调用之前(此节点的父节点)。
如果需要,您也可以按相反的顺序进行删除
free
相同的原则只是在转到下一个节点之前删除此节点。这意味着您不需要修复void ft_list_clear(string Node *list)
{
if (!list) { return; }
struct Node *next = list->next;
free(list);
ft_list_clear(next);
}
指针,但您需要先复制它们,这样就不会丢失引用。
答案 1 :(得分:1)
我认为这是因为你只是释放节点,但是你错过了next
成员的无效。试试这个。我没有这么好运。
void ft_list_clear(struct Node *begin_list)
{
if ((begin_list->next))
{
ft_list_clear(begin_list->next);
begin_list->next = NULL; // <-- you should nullify the next of the current after you free the node which it points to.
}
if(!(begin_list->next)) // <-- even if the next node was deleted, this won't run if you didn't nullify begin_list->next
{
free(begin_list);
begin_list = NULL;
}
}
答案 2 :(得分:1)
这个问题
void ft_list_clear(struct Node *begin_list)
{
if ((begin_list->next))
ft_list_clear(begin_list->next);
if(!(begin_list->next))
{
free(begin_list);
begin_list = NULL;
}
}
是:
begin_list
等于head
。head->next
不是NULL
,因此执行ft_list_clear(second)
second->next
不是NULL
,因此执行ft_list_clear(third)
third->next
为NULL
,因此发生了free(third)
。 begin_list = NULL
line在这里什么也没做,没有意义。第三次迭代返回第二次。下一行要执行
if(!(begin_list->next))
begin_list->next
不 NULL(它只是free
d),因此条件评估为false
和{{1 }}
未执行。
这是可行的递归:
free
答案 3 :(得分:0)
`void ft_list_clear(struct Node * begin_list)
{
if ((begin_list->next))
ft_list_clear(begin_list->next);
free(begin_list);
begin_list = NULL;
printf("God bless America");
}`
希望,如果上帝保佑美国三次,你的代码正在运行,我已经对你的代码进行了一些修改,而我所做的就是删除第二个if语句,因为通常,我们不需要递归(I')我并不是说如果声明我们不需要多于一个)。自己测试,你会明白为什么会这样。希望它有所帮助。
答案 4 :(得分:0)
递归删除链接是 坏主意 。每个递归调用都需要一个堆栈帧,无论是在下降还是递增递归时释放列表节点内存,都需要O(n)内存来进行简单的操作。每个堆栈调用都需要本地变量存储,返回指针空间,前一个堆栈帧指针以及可能的其他内容(每个节点至少12-24个字节)。
最好迭代列表。我提供了三种免费变体(迭代,两个递归,一个自由下降的节点,一个自由的上升节点)。
#include <stdlib.h>
#include <stdio.h>
typedef struct Node
{
int data;
struct Node* next;
} node_t;
long list_clear_iter(node_t* p) {
if(!p) return 0;
long n = 0; //count;
for( ; p->next; ) {
node_t* fp = p; //free this
p = p->next;
free(fp);
++n;
}
return n;
}
//list clear, recursive, (pre)free
long ft_list_clear_pr(node_t* p) {
if(!p) return 0;
node_t* np = p->next;
free(p); //free on descend
long n = ft_list_clear_pr(np);
return(n+1);
}
//list clear recursive, free(post)
long ft_list_clear_rp(node_t* p) {
if(!p) return 0;
long n = ft_list_clear_rp(p->next);
free(p); //free on ascend
return(n+1);
}