链表遍历 **while(thead != NULL)** 和 while(thead->next !=NULL) 的区别
Posted
技术标签:
【中文标题】链表遍历 **while(thead != NULL)** 和 while(thead->next !=NULL) 的区别【英文标题】:Difference between linked list traversal **while(thead != NULL)** and while(thead->next !=NULL) 【发布时间】:2017-11-15 18:28:34 【问题描述】:谁能告诉我 while(thead != NULL) 和 while(thead->next !=NULL) 有什么区别,因为用于遍历列表 thead != NULL 不工作,而 thead->next 工作。 据我了解,头节点只是指向起始节点的指针,而不是起始节点本身。See this if u have doubt.这里的头只是存储地址。
//thead 表示临时头变量,用于存储头指向的地址。 这是插入的代码。
#include<stdio.h>
#include<malloc.h>
#include<stdlib.h>
struct node
int data;
struct node *next;
;
struct node *head;
void insert(int x)
struct node *temp=(struct node *)malloc(sizeof(struct node));
temp->data=x;
temp->next=NULL;
if(head==NULL)
head=temp;
else
struct node * thead;
thead=head;
while(thead->next!=NULL)
thead=thead->next;
thead->next=temp;
void print()
struct node *temp;
temp=head;
while(temp!=NULL)
printf("%d",temp->data);
temp=temp->next;
int main()
head=NULL;
int i,n,x;
printf("enter number of nodes");
scanf("%d",&n);
for(i=0;i<n;i++)
printf("enter no");
scanf("%d",&x);
insert(x);
print();
如果我们将 thead ->next != NULL 替换为 thead !=NULL 则 dev c++ 停止工作。反之亦然,在 printf 中进行遍历...
那么有人可以回答上述两者之间的区别吗?
另外,头节点是第一个包含数据和地址的节点,还是只存储上图中的地址?
另外,如果头节点只是一个存储地址的指针,那么我们如何访问 thead->next 呢?
什么时候指向结构的指针为NULL?
谢谢
【问题讨论】:
刚刚添加了整个代码 尝试自己回答以下问题。thead==NULL
条件在此范围内意味着什么? thead->next==NULL
条件在此范围内意味着什么?
如果 thread 等于 NULL,则 thread->next = temp 尝试取消引用 NULL 指针。
@AbhishekBansal 你提到的条件在这个算法中可能吗?
如果代码使用while(thead != NULL) ...
,那么在循环之后,应该将什么设置为temp
?需要设置为temp
的是一些.next
成员,但是什么指针?
【参考方案1】:
既然我已经真正理解了......对于那些仍然被困的人,我正在写这个......
当我使用 (thead!=NULL) 时,thead 指针实际上指向列表中的每个元素。当它到达最后一个元素时,它仍然遍历到下一个为 NULL 的元素,这与 (thead->next! =NULL) 在链表的最后一个元素处停止。
在打印的情况下,我们需要打印列表中的所有值,所以我们使用 while(thead!=NULL) 因为我们也需要打印最后一个元素。对于遍历,我们只需让指针指向最后一个元素节点,这样我们就可以在它处停下来,直到我们到达 NULL 指针才遍历。
我们无法取消对 NULL 的引用,因此出现了错误。
【讨论】:
【参考方案2】:使用print()
,代码不需要记住循环后的最后一个节点地址
temp=head;
while(temp!=NULL)
printf("%d",temp->data);
temp=temp->next;
// temp == NULL at this point and code does not care what the last node was.
使用insert()
,代码确实需要记住循环后的最后一个节点地址。
// First handle special case where the head of the list is NULL
// otherwise ....
while(thead->next!=NULL)
thead = thead->next;
// temp->next == NULL at this point
// Code can use `thead` to access the last node's members.
thead->next = temp;
头节点是第一个包含数据和地址的节点,还是只存储上图中的地址?
struct node *head
是一个指针。当head != NULL
时,它指向包含数据的第一个节点和一个next指针。
如果头节点只是一个存储地址的指针,那么我们如何访问 thead->next ?
thead
被初始化为head
。通过取消引用thead
,代码可以访问该节点的成员,包括.next
。
什么时候指向结构的指针是NULL?
问题不清楚。指向struct
的指针在其值等于NULL
时为NULL
。这通常作为链表代码的结尾。
【讨论】:
你能回答最后 3 个问题,让我更清楚吗? @Shaurya 为什么你编码struct node *temp=(struct node *)malloc(sizeof(struct node));
而不是更简单的struct node *temp=malloc(sizeof(struct node));
甚至更好的struct node *temp = malloc(sizeof *temp);
?最后一个是首选。
malloc 返回一个 void 指针,表示内存已分配但与任何数据类型无关。所以实际上我在这里对用户生成的数据类型进行类型转换,即 (struct node*)。
@Shaurya C 不需要演员表来工作 - 这是不必要的。如果WET,则使用struct node *temp=(struct node *)malloc(sizeof(struct node));
。如果DRY,则使用struct node *temp = malloc(sizeof *temp);
[错误] 从 'void*' 到 'node*' 的无效转换 [-fpermissive] 实施你的建议会在 dev c++ 中出现此错误。以上是关于链表遍历 **while(thead != NULL)** 和 while(thead->next !=NULL) 的区别的主要内容,如果未能解决你的问题,请参考以下文章
876. Middle of the Linked List - LeetCode