题目;
输入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.,
这会导致你失去对链表头的引用,因为 head
的 next
指针被赋值为 p
,而不是链表的头。
所以,这样的更改会导致在之后的程序执行中无法正确访问整个链表的数据。正确的做法是保持 head
不变,而通过 head->next
来遍历链表,因为 head->next
是指向链表的第一个节点的
总结就是
在建链表的时候
我们使用的是
tail->next=p;
因为设置新的结点
而接收头指针
p=head->next;
我们不能修改头指针,只能将其赋值