链表遍历 **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-&gt;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

链表

15合并两个排序的链表

[leetcode]82. Remove Duplicates from Sorted List

反转链表 leetcode206

反转链表 leetcode206