节点易混点 指针域的赋值修改

文章讲述了如何使用C语言创建一个单链表,包括节点结构定义、链表创建函数`creat`以及如何正确遍历链表。关键步骤在于正确设置节点的后继指针和维护链表头部指针的指向。
摘要由CSDN通过智能技术生成

题目;

输入N个整数,按照输入的顺序建立单链表存储,并遍历所建立的单链表,输出这些数据。

输入格式:

第一行输入整数的个数N;

第二行依次输入每个整数。

输出格式:

输出这组整数。

输入样例:

8
12 56 4 6 55 15 33 62

输出样例:

12 56 4 6 55 15 33 62

代码长度限制

16 KB

时间限制

400 ms

内存限制

64 MB

栈限制

8192 KB

#include<stdio.h>
#include<stdlib.h>

typedef struct node{
    int data;
    struct node *next;
}node;

node* creat(int n){
    node *head,*tail,*p;
    head=malloc(sizeof(node));
    head->next=NULL;
    tail=head;
    int i;
    for(i=0;i<n;i++){ 
        p=malloc(sizeof(node));
        scanf("%d",&p->data);
         p->next=NULL;
         tail->next=p; //q1:为什么不是p=tail->next;
        tail=p;
    }
    return head;
}

int main(){
int i,n;
    scanf("%d",&n);
    node *head;
    node *p;
    head=malloc(sizeof(node));
    p=malloc(sizeof(node));
    head->next=NULL;
    head=creat(n);
    
    p=head->next;//q2:为什么不是head->next=p;
    for(i=0;i<n;i++){
        printf("%d",p->data);
            if(i<n-1)printf(" ");
        p=p->next;
    }
return 0;
}

 建立链表正向建立的过程是

首先我们是顶一个一种结点的结构体,因为后面我们还要重复使用定义的结构体,所以我们这里是使用了typedef 来给结构体起一个别名,直接在最后加一个node即可

其次我们使用函数来实现创建链表

node* creat(int n){
    node *head,*tail,*p;
    head=malloc(sizeof(node));
    head->next=NULL;
    tail=head;
    int i;
    for(i=0;i<n;i++){
        p=malloc(sizeof(node));
        p->next=NULL;
        scanf("%d",&p->data);
        tail->next=p;
        tail=p;
    }
    return head;
}

这是正向建立链表的函数

每次新结点都是在链表中的最后一个

我们首先定义三个结点

头结点定义,分配内存,指针指向

如何让tail=head;也就是此时二者的处境是一样的

然后就是我们插入的新的结点

要插入n个我们就直接一个循环一次搞定

对于每一个结点我们要做的 首先是分配内存,每一个都要这样做,然后后继指针指向是空的,然后输入结点的数据域,最重要的是我们如何修改指针域,来保证每次输入的都是最后一个结点,并且切实可行的进行循环

对于每一个新的结点

tail->next=p;  //这一步是将新的结点挂载最后一个结点的后面  将tail的后继指针指向p

tail=p;   //最后将最后一个结点赋值给p

可是此处为什么不是

p=tial->next;

不也是挂载在最后一个结点后面的操作,为什么这样不对呢

如果这样做的话,实际意思是,将tail->next赋值给p,而tail->next是没有初始化的内存,将p赋值给没有初始化的内存,那p就是空的了,所以将 p 指向 tail->next 会使 p 成为一个未初始化的指针,所以是不对的

而在主函数中

我们用头结点接收之后,开始循环的时候是新的结点

int main(){
int i,n;
  scanf("%d",&n);
    node *head;
    node *p;
    head=malloc(sizeof(node));
    p=malloc(sizeof(node));
    head->next=NULL;
    head=creat(n);
        p=head->next;//____________________q2
        for(i=0;i<n;i++){
        printf("%d",p->data);
            if(i<n-1)printf(" ");
        p=p->next;
    }
return 0;
}

而同样的问题

如果我们q2这里是head->next=p;

为什么也会不对

head->next=p;这句执行的操作意思是将head的指针指向p.,

这会导致你失去对链表头的引用,因为 headnext 指针被赋值为 p,而不是链表的头。

所以,这样的更改会导致在之后的程序执行中无法正确访问整个链表的数据。正确的做法是保持 head 不变,而通过 head->next 来遍历链表,因为 head->next 是指向链表的第一个节点的

总结就是

在建链表的时候

我们使用的是

tail->next=p;

因为设置新的结点

而接收头指针

p=head->next;

我们不能修改头指针,只能将其赋值

  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值