//linked_list_1
#include<stdio.h>
#include<stdlib.h>
struct list
{
int data;
struct list *link;
};
int main()
{
struct list *ll=NULL, *tp=NULL;
int n=3, i;
ll=(struct list *)malloc(sizeof(struct list));
scanf("%d",&ll->data);
for(i=1; i<n; i++)
{
tp=(struct list *)malloc(sizeof(struct list));
scanf("%d",&tp->data);
ll->link=tp;
ll=ll->link;
}
ll->link=NULL;
while(ll)
{
printf("n%d",ll->data);
ll=ll->link;
}
}
//linked_list_2
#include<stdio.h>
#include<stdlib.h>
struct list
{
int data;
struct list *link;
};
void linked_list(struct list *,int);
int main()
{
struct list *ll=NULL;
int n=3;
ll=(struct list *)malloc(sizeof(struct list));
linked_list(ll,n);
while(ll)
{
printf("n%d",ll->data);
ll=ll->link;
}
}
void linked_list(struct list *kk, int n)
{
struct list *tp=NULL;
int i;
scanf("%d",&kk->data);
for(i=1; i<n; i++)
{
tp=(struct list *)malloc(sizeof(struct list));
scanf("%d",&tp->data);
kk->link=tp;
kk=kk->link;
}
kk->link=NULL;
}
两个程序是相同的,第二个程序是使用函数创建链表:void linked_list(struct list *kk, int n)
第一个程序也是链表创建,但没有任何功能。第二个程序工作正常,但第一个程序没有以正确的方式工作。
如果两个程序的输入都2 5 4
,则第二个程序输出2 5 4
但第一个程序输出仅4
。
为什么第一个程序没有以正确的方式工作?原因是什么?
第一个程序的问题在于,当你接受输入时,你正在移动链表的头部。因此,当您完成输入时,链表的头部现在位于其最后一个节点。然后,当您尝试打印出链表时,您只是获得了它的最后一个节点,因为当您进行最后一次输入时,头部被移动到那里。
理想情况下,您应该使用临时指针,将其与链表的头部指针对齐,然后获取输入,分配并移动它,并继续仅使用它构建链表。链表的头部指针(此处ll
(初始化后不应像这样移动:
ll=ll->link; //Wrong!
直到绝对需要这样做。这将导致链表被截断,您将丢失节点。
理想情况下,您的代码应该是这样的:
ll=(struct list *)malloc(sizeof(struct list));
tp = ll; //Align the temporary pointer with the head of the linked list.
scanf("%d",&tp->data);
for(i=1; i<n; i++)
{
//Allocate memory to the link of the temporary pointer since it is also a type of struct list.
tp->link=(struct list *)malloc(sizeof(struct list));
scanf("%d",&tp->link->data);
tp = tp->link; //Move only the temporary pointer.
}
tp->link=NULL; //Finally assign NULL when done taking inputs.
请注意,我只使用临时指针来执行所有操作。
第二个程序工作的原因是,您将头部指针的地址传递给用于构建链表的函数。现在,此函数获取kk
中地址的副本,该地址是链表的起始地址,并使用它在那里构建链表。但回到main()
,ll
指针仍然保存您最初分配内存的原始地址。因此,当您回到打印main()
时构建链表后,您从链表的实际头部开始,ll
并且您可以打印出整个链表。
但这仍然具有我之前提到的相同缺陷。您在打印链表时移动链表的头部(即ll
(。
while(ll)
{
printf("n%d",ll->data);
ll=ll->link; //This is wrong!
}
因此,在打印完链表后,链表的头部现在为 NULL。因此,如果您想在打印后对实际的链表执行某些操作,现在是不可能的,因为您已经将 head 设为 NULL。因此,解决方案再次使用临时指针将其与链表的头部对齐,然后使用它来打印出链表。像这样:
struct list *tp = ll;
while(tp)
{
printf("n%d",tp->data);
tp=tp->link;
}