本次对链表的操作以学生信息作为链表中存储的节点
其中链表每个节点的结构信息如下,先附上每个功能的函数代码,全部程序代码地址:https://blog.csdn.net/qq_43853160/article/details/101194607, 代码中用到的KeepScreen()为自定义的保留屏幕函数,每个case 后面为自定义的枚举
//组成学生链表的节点
typedef struct Student
{
int id; /*学号 */
char name[32]; /*姓名 */
char major[32]; /*专业 */
float score; /*成绩 */
struct Student *next;/*指向下一节点*/
}StuInfo;
1.创建(在尾部增加一个节点)
本次创建不带头节点的链表,对于插入删除等对链表修改的操作可选择返回头指针或传入二级指针如
void Add(StuInfo **head);
/**************************************
*创建学生链表
*尾插法
*************************************/
StuInfo *AddStudent()
{
StuInfo *phead = NULL;
StuInfo *pnew = NULL;
StuInfo *plast ;
char sel[] = "yes";
int IsRuning = 1;
while(IsRuning)
{
pnew = (StuInfo *)malloc(sizeof(StuInfo));
if(!pnew)
{
perror("malloc pnew: ");
printf("malloc pnew failed ...\n");
return phead;
}
printf("请输入姓名:");
scanf("%s", pnew->name);
getchar();
printf("请输入专业:");
scanf("%s", pnew->major);
getchar();
printf("请输入成绩:");
scanf("%f", &pnew->score);
getchar();
pnew->id = num;
pnew->next = NULL;
num ++;
//尾插法创建
if(NULL ==phead)
{
phead = pnew;
}
else
{
plast = phead;//表示最后一个结点,首先找到最后一个结点
while( plast->next != NULL)
{
plast = plast->next;
}
plast->next = pnew;
}
printf("是否继续添加学生信息?(yes/no):\n");
scanf("%s", sel);
getchar();
if(strcmp(sel, "no") == 0 || strcmp(sel, "NO") == 0)
{
system("clear");
printf("\t\t\t\n\n添加成功...\n");
break;
}
}
return phead;
}
2. 删除一个节点
/***********************************************
*根据学号删除一个学生
* *********************************************/
StuInfo *DelStudent(StuInfo *head)
{
if(NULL == head)
{
printf("当前没有存入学生无法删除!!!\n");
KeepScreen();
return head;
}
int id;
char ch[8];
StuInfo *p = head;
StuInfo *pre = head;//用于保存要删除节点的前一个节点
ShowStudent(head); //先打印一下整个链表方便从中查找
printf("请输入要删除的学号:");
scanf("%d", &id);
getchar();
//先找到要删除的节点
while(NULL != p)
{
if(id == p->id)
{
break;
}
p = p->next;
}
if(NULL == p)//当p==NULL时说明根据学号查找节点时没找到
{
printf("输入的学号不存在!!!\n");
KeepScreen();
return head;
}
printf("是否确认删除?(yes/no): ");
scanf("%s", ch);
getchar();
if(0 == strcmp(ch, "yes") || 0 == strcmp(ch, "YES"))
{
if(head == p)//如果要删除的节点是链表的第一个节点
{
head = head->next;
}
else//如果要删除的节点在链表中间或尾部
{
pre = head;
while(pre->next != p)
{
pre = pre->next;
}
/**************************************
*创建学生链表
*尾插法
*************************************/
StuInfo *AddStudent()
{
StuInfo *phead = NULL;
StuInfo *pnew = NULL;
StuInfo *plast ;
char sel[] = "yes";
int IsRuning = 1;
while(IsRuning)
{
pnew = (StuInfo *)malloc(sizeof(StuInfo));
if(!pnew)
{
perror("malloc pnew: ");
printf("malloc pnew failed ...\n");
return phead;
}
printf("请输入姓名:");
scanf("%s", pnew->name);
getchar();
printf("请输入专业:");
scanf("%s", pnew->major);
getchar();
printf("请输入成绩:");
scanf("%f", &pnew->score);
getchar();
pnew->id = num;
pnew->next = NULL;
num ++;
//尾插法创建
if(NULL ==phead)
{
phead = pnew;
}
else
{
plast = phead;//表示最后一个结点,首先找到最后一个结点
while( plast->next != NULL)
{
plast = plast->next;
}
plast->next = pnew;
}
printf("是否继续添加学生信息?(yes/no):\n");
scanf("%s", sel);
getchar();
if(strcmp(sel, "no") == 0 || strcmp(sel, "NO") == 0)
{
system("clear");
printf("\t\t\t\n\n添加成功...\n");
break;
}
}
return phead;
}
pre->next = p->next;
free(p);
}
printf("删除学号为%d的学生成功...\n", id);
KeepScreen();
}
else
{
printf("没有进行删除...\n");
KeepScreen();
}
return head;
}
3.修改学生信息(修改节点内容)
/***********************************************
*修改姓名/成绩/专业
* *********************************************/
void ModifyStudentInfo(StuInfo **head)
{
if(NULL == *head)
{
printf("当前没有学生,不可修改...\n");
KeepScreen();
return ;
}
int id;
int select;
int IsStop = 0;
printf("请输入要修改学生的id:");
scanf("%d", &id);
getchar();
StuInfo *p = *head;
while(NULL != p)
{
if(id == p->id)
{
break;
}
p = p->next;
}
if(NULL == p)
{
printf("不存在ID为%d的学生...\n", id);
KeepScreen();
return ;
}
while(!IsStop)
{
system("clear");
printf("\t\t\t*************************\n");
printf("\t\t\t* 请输入选项: *\n");
printf("\t\t\t* 1.修改姓名 *\n");
printf("\t\t\t* 2.修改成绩 *\n");
printf("\t\t\t* 3.修改专业 *\n");
printf("\t\t\t* 0.返回上一级 *\n");
printf("\t\t\t*************************\n");
scanf("%d", &select);
getchar();
switch(select)
{
case MODIFYNAME: //1 事先定义好的枚举
ModifyStuByName(p);
break;
case MODIFYSCORE://2
ModifyStuByScore(p);
break;
case MODIFYMAJOR://3
ModifyStuByMajor(p);
break;
case RETURN://0
default:
IsStop = 1;
break;
}
}
}
/***********************************************
*修改姓名
* *********************************************/
void ModifyStuByName(StuInfo *p)
{
printf("请输入新姓名:");
scanf("%s", p->name);
getchar();
printf("修改成功...\n");
KeepScreen();
}
/***********************************************
*修改成绩
* *********************************************/
void ModifyStuByScore(StuInfo *p)
{
printf("请输入新成绩:");
scanf("%f", &p->score);
getchar();
printf("修改成功...\n");
KeepScreen();
}
/***********************************************
*修改专业
* *********************************************/
void ModifyStuByMajor(StuInfo *p)
{
printf("请输入新专业:");
scanf("%s", p->major);
getchar();
printf("修改成功...\n");
KeepScreen();
}
4.查找学生节点并打印节点内容
/**************************************************
*根据学号/姓名查找学生节点
* ************************************************/
void QueryStudentFromLinkTable(StuInfo *head)
{
if(NULL == head)
{
printf("当前没有学生...\n");
KeepScreen();
return ;
}
int select;
int IsStop = 0;
while(!IsStop)
{
system("clear");
printf("\t\t\t*************************\n");
printf("\t\t\t* 请输入选项: *\n");
printf("\t\t\t* 1.根据学号查找 *\n");
printf("\t\t\t* 2.根据姓名查找 *\n");
printf("\t\t\t* 0.返回上一级 *\n");
printf("\t\t\t*************************\n");
scanf("%d", &select);
getchar();
switch(select)
{
case QUERYID:
QueryStuById(head);
break;
case QUERYNAME:
QueryStuByName(head);
break;
case RETURN:
default:
IsStop = 1;
break;
}
}
}
/***********************************************
*根据学号查找
* *********************************************/
void QueryStuById(StuInfo *head)
{
if(NULL == head)
{
return ;
}
int id;
StuInfo *p = head;
printf("请输入要查找的ID: ");
scanf("%d", &id);
getchar();
while(p)
{
if(id == p->id)
{
break;
}
p = p->next;
}
if(NULL == p)
{
printf("输入的ID不存在...\n");
KeepScreen();
return ;
}
printf("该学生信息如下:\n");
printf("\t\t\t学号\t姓名\t专业\t成绩\n");
printf("\t\t\t%d\t%s\t%s\t%f\n", p->id, p->name, p->major, p->score);
KeepScreen();
}
/***********************************************
*根据姓名查找
* *********************************************/
void QueryStuByName(StuInfo *head)
{
if(NULL == head)
{
return ;
}
char name[32];
StuInfo *p = head;
printf("请输入要查找的学生姓名: ");
scanf("%s", name);
getchar();
while(p)
{
if(0 == strcmp(name, p->name))
{
break;
}
p = p->next;
}
if(NULL == p)
{
printf("输入的姓名不存在...\n");
KeepScreen();
return ;
}
printf("该学生信息如下:\n");
printf("\t\t\t学号\t姓名\t专业\t成绩\n");
printf("\t\t\t%d\t%s\t%s\t%f\n", p->id, p->name, p->major, p->score);
KeepScreen();
}
5.摧毁整条链表(删除全部学生)
/**************************************************
*摧毁整个链表
* ************************************************/
void DestroyLinkTable(StuInfo **head)
{
if(NULL == *head)
{
printf("当前没有存入学生...\n");
KeepScreen();
return ;
}
StuInfo *p = *head;
while(NULL != *head)
{
p = *head;
*head = (*head)->next;
free(p);
}
printf("摧毁成功...\n");
KeepScreen();
}
6.打印每个节点信息
/**********************************************
*打印一条学生链表信息
*需传入头指针
* ********************************************/
void ShowStudent(StuInfo *head)
{
if(NULL ==head)
{
printf("当前没有存入学生 ...\n");
KeepScreen();
return ;
}
StuInfo *p = head;
printf("\t\t\t学号\t姓名\t成绩\t专业\n");
while(p)
{
printf("\t\t\t%d\t%s\t%.2f\t%s\n", p->id, p->name, p->score, p->major);
p = p->next;
}
KeepScreen();
}