/* ***********************************************************************************************
任务目的:
建立链表,输出链表,删除链表中的特定节点,在链表中插入新节点。
*********************************************************************************************** */
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#define SIZE sizeof(struct student) //用SIZE替代结构体student的长度
struct student *creat (void); //声明链表创建函数,且返回链表的首地址*head
struct student *cut (struct student *p_c, long num_c); //声明删除函数,删除链表中学号为num_c的节点
struct student *add (struct student *p_a, long num_a); //声明插入函数,链表中插入学号为num_a的节点
void print (struct student *p); //声明打印函数,无返回值
int n; //全局变量n记录链表中含有的节点数
struct student //结构体节点基本结构
{
long num; //学号
float score; //分数
struct student *next; //指向下一个节点的指针
};
void main ()
{
struct student *pstu, *pst, *pstud; //临时指针用以传递creat函数的返回值(链表的首地址)
long stu_cut, stu_add;
pstu = creat (); //创建链表
printf ("\n\nThere are %d records.\n", n); //打印n的值
printf ("\n\n");
print (pstu); //打印链表
printf ("\n\n");
printf ("Input the student number:"); //输入要删除的学生学号
scanf ("%d", &stu_cut);
pst = cut (pstu, stu_cut); //删除特定节点
printf ("\n\nNow, there are %d records.\n", n); //打印删除后n的值
printf ("\n\n");
print (pst); //打印删除节点后的链表
printf ("\n\n");
printf ("Input the student number:"); //输入要插入学生学号
scanf ("%d", &stu_add);
pstud = add (pst, stu_add); //插入特定节点
printf ("\n\nNow, there are %d records.\n", n);
printf ("\n\n");
print (pstud); //打印插入新节点后的链表
printf ("\n\n");
system ("pause");
}
struct student *creat (void) //创建链表结构的函数模块
{
struct student *head, *p1, *p2; //最终*head指向链表首地址,*p1指向下一节点
//*p2指向上一地址,将p2的*next与p1连接
head = NULL; //对head和n进行初始化
n = 0;
p1 = (struct student *)malloc(SIZE); //创建第一个新节点,并让p1指向该节点
if (p1 == NULL) //检测malloc函数返回值是否为NULL
{
printf ("Insufficient Memory!\n"); //以判别是否成功分配内存
}
else //如果成功分配内存,继续函数进程
{
head = p1; //将*head指向第一个节点的首地址
do
{
p2 = p1; //将*p2指向*p1所指的节点
printf ("Input student number:"); //输入节点的信息
scanf ("%d", &p1->num);
printf ("Input score of the student:");
scanf ("%f", &p1->score);
n++; //节点计数加1
p1 = (struct student *)malloc(SIZE); //分配一个新的节点,且将*p1指向它
p2->next = p1; //将p2的*next指向新节点(p1的地址)
} while (p2->num); //如果*p2的num(学号)不为0则进行循环
p1 = NULL;
}
n--; //因为最后输入0,n也自加了
return (head); //返回*head
}
void print (struct student *p) //创建打印链表的函数模块
{
if (p->num != 0) //如果这一节点学号信息为0则不打印
{
printf ("The score of student %d is %f\n", p->num, p->score);
//依次打印某节点中的信息(学号和成绩)
print (p->next); //对这一节点的*next继续调用print函数
}
else
{
printf ("That's all records.\n");
}
}
struct student *cut (struct student *p_c, long num_c) //删除函数模块
{
struct student *p_c1, *p_c2;
if (p_c == NULL) //判断链表是否为NULL
{
printf ("This is a Empty Chain.\n");
}
else
{
n--; //链表记录数减1
p_c1 = p_c; //将*p_c1指向第一个节点(*p_c或*head所指)
if (p_c1->num == num_c) //判断第一个节点是否为被删除节点
{
p_c = p_c1->next; //如果是,将链表首地址指向第二个节点首地址
}
else
{
do
{
p_c2 = p_c1; //*p_c2接手*p_c1所指的节点
p_c1 = p_c1->next; //*p_c1指向下一节点
if (p_c1 == NULL)
{
printf ("There is no such student in this Chain.\n\n");
break;
} //如果*p_c1所指为NULL,则此链表无该删除对象
else if (p_c1->num == num_c) //如果*p_c1学号与num_c相等则该节点需被删除
{
p_c2->next = p_c1->next; //将*p_c1中*next的地址取代*p_c2中*next的地址
break;
}
} while (p_c1->num);
}
}
return (p_c); //返回新链表的首地址
}
struct student *add (struct student *p_a, long num_a)
{
struct student *p_a1, *p_a2, *p_a0;
p_a0 = (struct student *)malloc(SIZE); //创建一个新结构体
p_a0->num = num_a; //将这个学生的学号导入新节点
printf ("Input the score of the sutdent:"); //输入这个学生的成绩
scanf ("%f", &p_a0->score);
p_a1 = p_a; //将*p_a1指向原链表的开头
if (p_a1 == NULL) //判断原链表是否为空表
{
printf ("This is an Empty Chain.\n");
}
else
{
n++; //链表中记录数加1
if (p_a1->num > p_a0->num) //如果新节点应放在链表首
{
p_a = p_a0; //将新节点首地址赋值给链表首地址
}
else
{
do
{
p_a2 = p_a1; //*p_a2接手原链表的当前节点
p_a1 = p_a1->next; //*p_a1指向原链表的下一节点
if (p_a1 == NULL)
{
break;
}
} while ((p_a1->num < p_a0->num) && (p_a1->next != NULL));
//当下一节点的学号小于插入学号且不为NULL
(p_a2->next) = p_a0; //新节点首地址赋值给“上一节点”的*next
}
p_a0->next = p_a1; //新节点的*next指向“下一节点”的首地址
}
return (p_a);
}