尝试了一下用链表存储学生学号成绩数据,从中还是遇到很多问题。
最初,删除节点的时候,我是不准备返回地址的
一开始是这样写删除的:
void stu_result *delet(struct stu_result *head,int i)
{
int j;
if(i==1)
{
head=head->next;
}
else
{
for(j=0;j<i-2;j++)/**************************************************************************
j<i-2是控制循环到需删除的节点的前一个地址
(比如要删除第2个节点他就不会进入循环因为head就是第2个节点的前一个,而如果要删除第3个节点时他就进行一次)
********************************************************************************************************/
{
head=head->next;
}
head->next=head->next->next;
}
}
如果删除的不是第一个节点当然没什么问题,但当删除第一个节点时,原来的链表是以头地址传输的,原来的链表并没有改变,所以当删除第一个节点时要返回一个新的链表头地址覆盖原来的链表。
完整正确的代码如下:
#include<stdio.h>
struct stu_result
{
int num;
float score;
struct stu_result *next;
};
struct stu_result *build();//创建链表
void prinf(struct stu_result *head);//输出链表
struct stu_result *delet(struct stu_result *head,int a);//链表的节点删除
int main()
{
int i;//i为需要删除的第几个链表元素
struct stu_result *stu;
stu=build();
printf("\n\n\n");
prinf(stu);
printf("您需要更改删除链表元素吗,如需要请输入链表第几个节点!\n");
scanf("%d",&i);
stu=delet(stu,i);
printf("\n\n");
prinf(stu);
}
struct stu_result *build()
{
int n;//指创建到第几个节点
struct stu_result student[100],*head,*p1,*p2
/*我利用数组来建立链表,也可以用malloc函数来建立链表 :"p1=(struct stu_result)malloc(sizeof(stu_result));"
p1和p2是方便用来指向新创建的节点的*/
p1=p2=&student[0];//p1,p2先初始化指向第一个节点
head=NULL;//初始化
printf("请输入学号(0结束):") ;
scanf("%d",&p1->num);
for(n=0;p1->num!=0;)//判断是否输入0,是否应该创建下一个节点
{
n=n+1;
if(n==1)//进行首次的节点创建(之后就用不着了)
{
head=p1;//head指向第一个节点
}
else//再次的指向新创建的节点
{
p2->next=p1;
}
printf("请输入分数:");
scanf("%f",&p1->score);
p2=p1;//(首次节点创建时用不着),从第二次后开始,p2与p1同步指向新节点
p1=&student[n];//开辟新节点
printf("请输入学号(0结束):");
scanf("%d",&p1->num);
}
p2->next=NULL;//结束最后一个节点,指向NULL
return head;//返回链表
}
void prinf(struct stu_result *head)
{
printf("\n\n");
while(head!=NULL)
{
printf("学号是%d\n",head->num);
printf("分数是%f\n",head->score);
head=head->next;
printf("\n");
}
}
struct stu_result *delet(struct stu_result *head,int i)
{
int j;
struct stu_result *newstu;//新链表
struct stu_result *p;//用来替换初始的head,方便返回原链表
p=head;
if(i==1)
{
p=p->next;
newstu=p;
return newstu;/************************
因为第一个节点改变了(最初的sut链表中的head改变)
所以他的头地址必须更新,返回一个新的头地址链表
***********************/
}
else
{
for(j=0;j<i-2;j++)/**************************************************************************
j<i-2是控制循环到需删除的节点的前一个地址
(比如要删除第2个节点他就不会进入循环因为head就是第2个节点的前一个,而如果要删除第3个节点时他就进行一次)
********************************************************************************************************/
{
p=p->next;
}
p->next=p->next->next;
return head;
/**********************
第一个节点没有改变(head不变),
根据链表的性质,指向下一个节点的地址。
所以返回原来的链表即可,无需返回新的链表
**********************************/
}
}