对于下面的链表声明,
#include <stdlib.h>
#include <stdio.h>
typedef struct list
{
int val;
struct list *next;
} list;
void destroy (list *l)
{
if (l)
{
destroy (l->next);
free (l);
}
}
为什么下面的主要工作
int main()
{
list *test;
list *ptr1, *ptr2;
int i;
test = malloc (sizeof (list));
test->val = 0;
ptr2 = test;
for (i = 1; i <= 10; i++)
{
ptr1 = (list *) malloc (sizeof (list));
ptr1->val = i;
ptr2->next = ptr1;
ptr2 = ptr1;
}
ptr1 = test;
while (ptr1)
{
printf ("%d\n", ptr1->val);
ptr1 = ptr1->next ;
}
destroy (test);
return 0;
}
虽然这个甚至不创建列表(它只创建一个节点)?
int main()
{
list *test;
list *ptr;
int i;
test = malloc (sizeof (list));
test->val = 0;
ptr = test->next;
for (i = 1; i <= 10; i++)
{
ptr = (list *) malloc (sizeof (list));
ptr->val = i;
ptr = ptr->next;
}
ptr = test;
while (ptr)
{
printf ("%d\n", ptr->val);
ptr = ptr->next ;
}
destroy (test);
return 0;
}
他们不是使用相同的逻辑吗?
最佳答案
代码
ptr = test->next;
for (i = 1; i <= 10; i++)
{
ptr = (list *) malloc (sizeof (list));
ptr->val = i;
ptr = ptr->next;
}
首先获取 test->next
的副本,但从不将任何内容分配给 test->next
本身。因此,从 test
开始的列表只有一个项目。更糟糕的是,该项目有一个未初始化的 next
指针,因此尝试遍历列表的代码几乎肯定会崩溃。
正如其他答案中所暗示的,对于每个新分配的节点都会重复这种模式。
在回答您的评论时,使第二个功能起作用的最佳方法是使其更像第一个(起作用的)版本。我已经重命名了其中的变量以使其更清晰
list *head;
list *next, *curr;
int i;
head = malloc (sizeof(*head));
head->val = 0;
curr= head;
for (i = 1; i <= 10; i++)
{
next = malloc (sizeof(*next));
next->val = i;
curr->next = next;
curr= next;
}
curr= head;
关于c - 链表实现差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16897127/