C语言,单链表实现(不含文件读入信息,单纯手动录入信息)
主要以学生ID,姓名和三课成绩进行操作
结构体定义
struct Node
{
char name[20]; // 学生姓名
char no[20]; // 学生学号
float score[3]; // score数组分别存储语文、数学、英语成绩
float total; // 总分
struct Node *next; // 下一个结点的地址
};
创建链表先上代码图
typedef struct Node *pNode;
//实现链表的创建(根据文件scores.txt读入)、排序、输出、节点查找、插入、删除
pNode create()//信息读入和链表创建 ,假定scores.txt的文件读入姓名-学号-成绩,每个人一行
{
//人数就三个,所以长度为三
pNode pHead=(pNode)malloc(sizeof(struct Node));
if(NULL==pHead)
{
printf("创建失败");
exit(-1);//检验是否成功
}
else
{
pNode pTail=pHead;//头尾节点
pHead->next=NULL;//头节点为空
for(i=0;i<3;i++)//长度可以自定义,循环创建
{
pNode p=(pNode)malloc(sizeof(struct Node));
if(p==NULL)
{
printf("创建失败");
exit(-1);//检验是否成功
}
else
{
//文件读入信息
scanf("%s",p->no);
scanf("%s",p->name);
scanf("%f",&(p->score[0]));
scanf("%f",&(p->score[1]));
scanf("%f",&(p->score[2]));
scanf("%f",&(p->total));
pTail->next=p; //不断 创建节点,最后总指向空
p->next=NULL;
pTail=p;
}
}
}
return pHead;
}
定义头尾节点,头节点为空指向下一个节点,所以信息打印的时候要跳过他,不然会乱码也就是从pHead->next开始
尾节点指向p,p指向下个空结点,然后尾节点指向空,这样保证每次都指向最末尾
关键代码
pNode pTail=pHead;//头尾节点
pHead->next=NULL;//头节点为空
pNode p=(pNode)malloc(sizeof(struct Node));//创建节点
pTail->next=p; //不断 创建节点,最后总指向空
p->next=NULL;
pTail=p;
数据打印
void print(pNode pHead)//数据打印
{
pNode p=pHead->next;//跳过头节点,头节点为空
while(p!=NULL)
{
printf("学号 \t姓名\t语文\t数学\t英语\t总分\n");
printf("%s \t%s\t%g\t%g\t%g\t%g\n",p->no,p->name,p->score[0],p->score[1],p->score[2],p->total);
p=p->next;
}
}
pNode p=pHead->next;//跳过头节点,头节点为空 ,这句话保证数据不出错,然后循环指向下一个
数据排序(选择)
void sort(pNode pHead)//排序 从小到大
{
int i,j;
pNode p,q;
for(i=0,p=pHead->next;i<2;i++,p=p->next)
{
for(j=i+1,q=p->next;j<3;j++,q=q->next)
{
//交换数据
if(strcmp(p->no,q->no)>0)
{
//交换数据
float temp;temp=p->total;p->total=q->total;q->total=temp;
temp=p->score[0];p->score[0]=q->score[0];q->score[0]=temp;
temp=p->score[1];p->score[1]=q->score[1];q->score[1]=temp;
temp=p->score[2];p->score[2]=q->score[2];q->score[2]=temp;
temp=p->total;p->total=q->total;q->total=temp;
char c[20];strcpy(c,p->no);strcpy(p->no,q->no);strcpy(q->no,c);
strcpy(c,p->name);strcpy(p->name,q->name);strcpy(q->name,c);
}
}
}
}
思路和数组交换差不多,定义两个节点p,q然后指向数据,开始进行交换,但都要跳过头节点,指向下一个,所以
p=pHead->next,q=p->next;这两句不能少,选择是这样,
交换用一个临时变量即可,c++有swap可以直接换,C语言只能自己写,字符数组交换用strcpy
查找数据
void find(pNode head,char ID[])//数据查找,根据ID查找
{
int flag=0;
if(head->next==NULL)
{
printf("error:空链表");
}
pNode p=head;
while(p!=NULL)
{
if(!strcmp(p->no,ID))
{
printf("学号 \t姓名\t语文\t数学\t英语\t总分\n");
printf("%s \t%s\t%g\t%g\t%g\t%g\n",p->no,p->name,p->score[0],p->score[1],p->score[2],p->total);
flag=1;
}
p=p->next;
}
if(!flag)
{
printf("记录中未有此人\n");
}
}
这和循环创建链表差不多,加了if判断罢了
删除数据
void delete(pNode head,char ID[])//数据删除
{
if(head->next==NULL)
{
printf("error:空链表\n");
exit(0);
}
pNode p=head;
head=head->next;
while(head!=NULL)
{
if(!strcmp(head->no,ID))
{
p->next=head->next;
free(head);
}
head=head->next;
p=p->next;
}
}
删除数据,先根据判断找节点,不断指向下一个节点,创立两个节点,一个在前,一个在后,即p,q,然后找到后,令前节点p指向q的下一个节点,然后释放q,不然有野指针
关键代码:
pNode p=head;
head=head->next;
if 找到
p->next=head->next;
free(head);
else
head=head->next;
p=p->next;
或者用q保存要删除节点的地址位置;也就是原来的head=head->next先不要,当找到后令q=p->next,让他指向下一个节点;
赋值:p->next=q->next
free(q)释放内存
代码
q=p->next;
p->next=q->next;
free(q);
插入数据
void insert(pNode pHead,int pos,char id[],char Name[],float chinese,float math,float english,float sum)//数据插入,前插
{
int i=0;
pNode p=pHead;
while((p!=NULL)&&(i<pos))
{
p=p->next;
i++;
}
if(p==NULL||i>pos)//插入位置非法
{
printf("插入位置非法");
exit(0);
}
pNode new_node=(pNode)malloc(sizeof(struct Node));
//数据插入
strcpy(new_node->name,Name);
strcpy(new_node->no,id);
new_node->score[0]=chinese;new_node->score[1]=math;new_node->score[2]=english;
new_node->total= sum;
new_node->next=p->next;
p->next=new_node;
}
这个和删除差不多,多了一个增加节点的问题,同时根据i的赋值,它可以从0开始也可以从1开始
创立一个节点,节点存信息,然后让这个节点指向之前节点
new_node->next=p->next;
p->next=new_node;
主函数调用
int main()
{
pNode head=create();
return 0;
}
全部代码
#include<stdio.h>
#include<string.h>
#include<math.h>
struct Node
{
char name[20]; // 学生姓名
char no[20]; // 学生学号
float score[3]; // score数组分别存储语文、数学、英语成绩
float total; // 总分
struct Node *next; // 下一个结点的地址
};
typedef struct Node *pNode;
//实现链表的创建(根据文件scores.txt读入)、排序、输出、节点查找、插入、删除
pNode create()//信息读入和链表创建 ,假定scores.txt的文件读入姓名-学号-成绩,每个人一行
{
//人数就三个,所以长度为三
pNode pHead=(pNode)malloc(sizeof(struct Node));
if(NULL==pHead)
{
printf("创建失败");
exit(-1);//检验是否成功
}
else
{
pNode pTail=pHead;//头尾节点
pHead->next=NULL;//头节点为空
for(i=0;i<3;i++)//长度可以自定义,循环创建
{
pNode p=(pNode)malloc(sizeof(struct Node));
if(p==NULL)
{
printf("创建失败");
exit(-1);//检验是否成功
}
else
{
//文件读入信息
scanf("%s",p->no);
scanf("%s",p->name);
scanf("%f",&(p->score[0]));
scanf("%f",&(p->score[1]));
scanf("%f",&(p->score[2]));
scanf("%f",&(p->total));
pTail->next=p; //不断 创建节点,最后总指向空
p->next=NULL;
pTail=p;
}
}
}
return pHead;
}
void insert(pNode pHead,int pos,char id[],char Name[],float chinese,float math,float english,float sum)//数据插入,前插
{
int i=0;
pNode p=pHead;
while((p!=NULL)&&(i<pos))
{
p=p->next;
i++;
}
if(p==NULL||i>pos)//插入位置非法
{
printf("插入位置非法");
exit(0);
}
pNode new_node=(pNode)malloc(sizeof(struct Node));
//数据插入
strcpy(new_node->name,Name);
strcpy(new_node->no,id);
new_node->score[0]=chinese;new_node->score[1]=math;new_node->score[2]=english;
new_node->total= sum;
new_node->next=p->next;
p->next=new_node;
}
void delete(pNode head,char ID[])//数据删除
{
if(head->next==NULL)
{
printf("error:空链表\n");
exit(0);
}
pNode p=head;
head=head->next;
while(head!=NULL)
{
if(!strcmp(head->no,ID))
{
p->next=head->next;
free(head);
}
head=head->next;
p=p->next;
}
}
void find(pNode head,char ID[])//数据查找,根据ID查找
{
int flag=0;
if(head->next==NULL)
{
printf("error:空链表");
}
pNode p=head;
while(p!=NULL)
{
if(!strcmp(p->no,ID))
{
printf("学号 \t姓名\t语文\t数学\t英语\t总分\n");
printf("%s \t%s\t%g\t%g\t%g\t%g\n",p->no,p->name,p->score[0],p->score[1],p->score[2],p->total);
flag=1;
}
p=p->next;
}
if(!flag)
{
printf("记录中未有此人\n");
}
}
void sort(pNode pHead)//排序 从小到大
{
int i,j;
pNode p,q;
for(i=0,p=pHead->next;i<2;i++,p=p->next)
{
for(j=i+1,q=p->next;j<3;j++,q=q->next)
{
//交换数据
if(strcmp(p->no,q->no)>0)
{
//交换数据
float temp;temp=p->total;p->total=q->total;q->total=temp;
temp=p->score[0];p->score[0]=q->score[0];q->score[0]=temp;
temp=p->score[1];p->score[1]=q->score[1];q->score[1]=temp;
temp=p->score[2];p->score[2]=q->score[2];q->score[2]=temp;
temp=p->total;p->total=q->total;q->total=temp;
char c[20];strcpy(c,p->no);strcpy(p->no,q->no);strcpy(q->no,c);
strcpy(c,p->name);strcpy(p->name,q->name);strcpy(q->name,c);
}
}
}
}
void print(pNode pHead)//数据打印
{
pNode p=pHead->next;//跳过头节点,头节点为空
while(p!=NULL)
{
printf("学号 \t姓名\t语文\t数学\t英语\t总分\n");
printf("%s \t%s\t%g\t%g\t%g\t%g\n",p->no,p->name,p->score[0],p->score[1],p->score[2],p->total);
p=p->next;
}
}
int main()
{
printf("==================================================\n输入数据:\n");
pNode head=create();
printf("\n");
print(head);
printf("===================================================\n排序后的数据:\n");
sort(head);
print(head);
printf("\n");
printf("===================================================\n查找数据(输入ID):\n");
char ID[20];
scanf("%s",ID);
printf("\n");
find(head,ID);
printf("====================================================\n删除数据(输入ID): \n");
scanf("%s",ID);
printf("\n");
delete(head,ID);
print(head);
printf("====================================================\n增加数据(从0开始编号,前插): \n");
char name[20],id[20];
float ch,ma,en,su;
int n;
scanf("%d%s%s%f%f%f%f",&n,id,name,&ch,&ma,&en,&su);
insert(head,n,id,name,ch,ma,en,su);//数据插入
printf("\n");
printf("=======================================================\n");
print(head);
printf("=======================================================\n");
return 0;
}
结果
参考博客:
学习心得:链表的操作
讲真这个讲的我是最明白的