课程设计报告
- 课程设计概述
本次数据结构课程设计共完成5个题目:成绩分析问题,哈夫曼编码器,迷宫问题,八皇后问题,农夫过河问题的求解。
使用环境:C语言。
编译环境:Visual Studio 2022。
- 课程设计题目
1.《成绩分析问题》
(1)实验内容:
成绩分析问题。
(2)问题描述:
设计并实现一个成绩分析系统,能够实现录入,保存一个班级学生多门课程的成绩,并对成绩进行分析等功能。
(3)需求分析:
经过分析,本系统需完成的主要功能如下:
- 通过键盘输入各学生的多门课程的成绩,建立相应的文件input.dat。
- 对文件input.dat中的数据进行处理,要求具有如下功能:
- 按各门课程成绩排序,并生成相应的文件输出。
- 计算每个人的平均成绩,按平均成绩排序,并生成文件。
- 求出各门课程的平均成绩,最高分,最低分,不及格人数,60~69分人数,70~79分人数,80~89分人数,90分以上人数。
- 根据姓名或学号查询某人的各门课程成绩,重名也要能处理。
(4)概要设计:
--=ADT=--
{
Student * SearchByName(Student *head, char *name)// 根据姓名查询学生信息
Student * SearchById(Student *head, char *id)// 根据学号查询学生信息
void Add(Student **head)// 添加一个学生
void Read(Student **head)// 读取文件中的学生信息
void Save(Student * head)// 保存学生信息到文件
void SortAndOutput(Student * head)// 按三门课程成绩排序并输出
void CalculateAverage(Student * head)// 计算每人三门课程的平均成绩并输出
void SortByAverageScoreAndOutput(Student * head)// 按三门课程平均成绩排序并输出
void Statistics(Student * head)// 统计三门课程各自的平均成绩,最高分,最低分,不及格人数,60~69分人数,70~79分人数,80~89分人数,90分以上人数
void ShowMenu() // 显示菜单
}
(5)存储结构:
typedef struct student {
char id[20]; // 学号
char name[20]; // 姓名
float math_score; // 数学成绩
float english_score; // 英语成绩
float computer_score; // 计算机成绩
float average; // 平均成绩
struct student * next; // 指向下一个学生的指针
} Student;
(6)设计思路:
链表数据结构:使用链表来存储学生信息,每个节点表示一个学生。链表的好处是可以动态地添加和删除节点,灵活处理不同数量的学生信息。
- 学生结构体:定义一个学生结构体,包含以下字段:学号、姓名、数学成绩、英语成绩、计算机成绩、平均成绩和指向下一个学生节点的指针。这样可以方便地存储和访问每个学生的相关信息。
- 功能函数:实现各种功能函数,如添加学生、读取文件、保存文件、排序等。这些函数通过操作链表来完成相关操作。
(7)关键算法:
- 冒泡排序算法:用于将学生根据指定的排序规则(如成绩)进行排序。冒泡排序算法的基本思想是比较相邻的两个元素,如果它们的顺序错误就交换位置,继续比较直到完成排序。在学生信息管理系统中,可以根据数学成绩、英语成绩或计算机成绩来排序学生信息。
- 遍历链表:通过使用循环遍历链表的每个节点,可以实现对链表中的数据进行访问、处理和输出等操作。遍历链表是获取每个学生信息、计算平均成绩以及输出结果的关键步骤。
- 文件读写:通过使用二进制文件读写方式,可以将学生信息保存到文件中,或从文件中读取学生信息。在学生信息管理系统中,可以将学生信息以二进制形式写入文件,并在需要时从文件中读取,并重新构建链表。
使用链表作为数据结构,结合冒泡排序算法、链表遍历和文件读写等算法,可以实现学生信息的管理、排序和存储等功能
(8)详细设计:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 定义学生结构体
typedef struct student {
char id[20]; // 学号
char name[20]; // 姓名
float math_score; // 数学成绩
float english_score; // 英语成绩
float computer_score; // 计算机成绩
float average; // 平均成绩
struct student * next; // 指向下一个学生的指针
} Student;
// 根据姓名查询学生信息
Student * SearchByName(Student *head, char *name) {
Student *p = head;
while (p != NULL) {
if (strcmp(p->name, name) == 0) { // 找到该学生
return p;
}
p = p->next;
}
return NULL; // 没有找到该学生
}
// 根据学号查询学生信息
Student * SearchById(Student *head, char *id) {
Student *p = head;
while (p != NULL) {
if (strcmp(p->id, id) == 0) { // 找到该学生
return p;
}
p = p->next;
}
return NULL; // 没有找到该学生
}
// 添加一个学生
void Add(Student **head) {
Student * p = (Student *)malloc(sizeof(Student));
printf("请输入学生的学号:");
scanf("%s", p->id);
printf("请输入学生的姓名:");
scanf("%s", p->name);
printf("请输入学生的数学成绩:");
scanf("%f", &p->math_score);
printf("请输入学生的英语成绩:");
scanf("%f", &p->english_score);
printf("请输入学生的计算机成绩:");
scanf("%f", &p->computer_score);
p->average = (p->math_score + p->english_score + p->computer_score) / 3; // 计算平均成绩
// 插入到链表中
Student * temp = NULL;
Student * cur = *head;
while(cur && p->average < cur->average) { // 按平均成绩排序插入
temp = cur;
cur = cur->next;
}
if(temp == NULL) {
p->next = *head;
*head = p;
} else {
temp->next = p;
p->next = cur;
}
printf("添加成功\n");
}
// 读取文件中的学生信息
void Read(Student **head) {
FILE * fp = fopen("input.dat", "rb");
if (fp == NULL) {
printf("文件打开失败\n");
return;
}
Student * p = (Student *)malloc(sizeof(Student));
fread(p, sizeof(Student), 1, fp);
while (!feof(fp)) {
// 插入到链表后面
p->next = *head;
*head = p;
p = (Student *)malloc(sizeof(Student));
fread(p, sizeof(Student), 1, fp);
}
printf("读取成功\n");
fclose(fp);
}
// 保存学生信息到文件
void Save(Student * head) {
FILE * fp = fopen("input.dat", "wb");
if (fp == NULL) {
printf("文件打开失败\n");
return;
}
Student * p = head;
while (p != NULL) {
fwrite(p, sizeof(Student), 1, fp);
p = p->next;
}
printf("保存成功\n");
fclose(fp);
}
// 按三门课程成绩排序并输出
void SortAndOutput(Student * head) {
Student * p = head;
int count = 0;
while (p != NULL) {
count++;
p = p->next;
}
Student ** array = (Student **)malloc(sizeof(Student *) * count); // 存储指针的数组
p = head;
for (int i = 0; i < count; i++) {
array[i] = p;
p = p->next;
}
for (int i = 0; i < count - 1; i++) { // 冒泡排序
for (int j = 0; j < count - 1 - i; j++) {
if (array[j]->math_score + array[j]->english_score + array[j]->computer_score < array[j + 1]->math_score + array[j + 1]->english_score + array[j + 1]->computer_score) {
Student * temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
FILE * fp = fopen("sorted_by_score.dat", "w");
fprintf(fp, "%-20s%-20s%-20s%-20s%-20s%-20s\n", "学号", "姓名", "数学成绩", "英语成绩", "计算机成绩", "平均成绩");
for (int i = 0; i < count; i++) {
fprintf(fp, "%-20s%-20s%-20.1f%-20.1f%-20.1f%-20.1f\n", array[i]->id, array[i]->name, array[i]->math_score, array[i]->english_score, array[i]->computer_score, array[i]->average);
}
printf("排序成功并已保存到sorted_by_score.dat文件中\n");
fclose(fp);
}
// 计算每人三门课程的平均成绩并输出
void CalculateAverage(Student * head) {
FILE * fp = fopen("average_score.dat", "w");
fprintf(fp, "%-20s%-20s%-20s%-20s%-20s%-20s\n", "学号", "姓名", "数学成绩", "英语成绩", "计算机成绩", "平均成绩");
Student * p = head;
while (p != NULL) {
fprintf(fp, "%-20s%-20s%-20.1f%-20.1f%-20.1f%-20.1f\n", p->id, p->name, p->math_score, p->english_score, p->computer_score, p->average);
p = p->next;
}
printf("每人三门课程的平均成绩已计算并保存到average_score.dat文件中\n");
fclose(fp);
}
// 按三门课程平均成绩排序并输出
void SortByAverageScoreAndOutput(Student * head) {
Student * p = head;
int count = 0;
while (p != NULL) {
count++;
p = p->next;
}
Student ** array = (Student **)malloc(sizeof(Student *) * count); // 存储指针的数组
p = head;
for (int i = 0; i < count; i++) {
array[i] = p;
p = p->next;
}
for (int i = 0; i < count - 1; i++) { // 冒泡排序
for (int j = 0; j < count - 1 - i; j++) {
if (array[j]->average < array[j + 1]->average) {
Student * temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
FILE * fp = fopen("sorted_by_average_score.dat", "w");
fprintf(fp, "%-20s%-20s%-20s%-20s%-20s%-20s\n", "学号", "姓名&#