题目举例
本关任务:用单向链表建立一张班级成绩单,包括每个学生的学号、姓名、英语、高等数学、普通物理、C语言程序设计四门课程的成绩。用菜单实现下列功能: ① 输入每个学生的各项信息。 ② 输出每个学生的各项信息。 ③ 修改指定学生的指定数据项的内容。 ④ 统计每个同学的平均成绩(保留2位小数)。 ⑤ 输出各位同学的学号、姓名、四门课程的总成绩和平均成绩。按照平均成绩进行升序排序的函数(重难点)。
一、类型定义部分
类型定义可以使结构体简洁明了,是不可或缺的准备工作
typedef struct _achievement//结点设置
{
char stunumber[16];
char name[8];
int english, math, physics,c;
struct _achievement* next;
}Achieve;
typedef struct _list//指向链表结点的指针集合
{
Achieve* head;
Achieve* target;
Achieve* left;
Achieve* right;
Achieve* left_front;
Achieve* tail;
}List;
1、第一个typedef是正常的链表结点的定义(包含数据域和指向下一个结点的指针)
2、第二个typedef是核心部分(听翁恺老师的链表课所获)核心思想:创建了一个整合包,里面打包了可以由你决定的指向任一结点的结点指针(类似于二级指针,因为这样才能把在函数内部对链表进行的操作保留到主函数中,传参注意把List的地址传过去)。
二、总调用函数
void exe()
{
int input;
List list;
void (*func[7])(List*) = { NULL, Input ,Put, Modify, Average, All ,Sort };//指向函数的指针数组,增加NULL是为了调用函数与输入的input相同
list.head = list.tail = list.target = list.target=list.left=list.right=list.left_front=NULL;//list中指针都需初始化
do {
scanf("%d", &input);
func[input](&list);
} while (input);
}
三、 输入函数
void Input(List* plist)//体现List的作用,传list的地址过来,主函数可以保留
{
int n = 0;//输入的人数
scanf("%d", &n);
Achieve* p = NULL;
for (int i = 0; i < n; i++)
{
p = (Achieve*)malloc(sizeof(Achieve));//p为新结点
scanf("%s%s%d%d%d%d", p->stunumber, p->name, &p->english, &p->math, &p->physics, &p->c);//将结点的数据域构建好
p->next = NULL;//next一定要指向NULL
if (plist->head)//判断是否有链表头
{
plist->tail->next = p;
plist->tail = plist->tail->next;//构建List时建立尾指针目的是便于接新结点
}
else//没有头要同时将p赋给头和尾
{
plist->head = plist->tail = p;
}
}
printf("完成了%d位同学的成绩输入。\n, n");
}
四、遍历输出
void Put(List* plist)
{
for (Achieve*p=plist->head; p; p=p->next)//建立遍历指向,以p存在为进入条件,每次循环结束,注意指向后移
{
printf("%s %s %d %d %d %d\n", p->stunumber, p->name, p->english, p->math, p->physics,p->c);
}
}
五、根据平均数排序(结点交换)
至今觉得还不够完善(以后会再来更新)
void Sort(List* plist)
{
int count = 0;//算人数
double aver_left, aver_right;
int k = 0;
for (Achieve* p = plist->head; p; p = p->next)
{
count++;
}
for (int i = 0; i < count-1; i++)
{
for (int j = 0; j < count - i - 1;j++)
{
for(k=0, plist->left = plist->head, plist->right = plist->head->next;k<j;k++)
{
plist->left_front = plist->left;
plist->left = plist->left->next;
plist->right = plist->right->next;
}//左右标的后移操作,类似于数组排序时的作比较的两个下标的后移(不足是从头开始,改进方法是从找得到得结点开始会更快)
aver_left = (double)(plist->left->english + plist->left->math + plist->left->physics + plist->left->c);
aver_right = (double)(plist->right->english + plist->right->math + plist->right->physics + plist->right->c);
if (aver_left > aver_right)//结点交换
{
if (j)
{
plist->left_front->next = plist->right;
plist->left->next = plist->right->next;
plist->left_front->next->next = plist->left;
}
else
{
plist->head = plist->right;
plist->left->next = plist->head->next;
plist->head->next = plist->left;
}
}
}
}
其余函数不多赘述。
1071

被折叠的 条评论
为什么被折叠?



