# USST-Datastruct_CourseSystem
`上海理工大学数据结构课程设计:课程信息管理系统`的设计实现。
## 项目要求
为某学校计算机专业开发一个课程信息管理软件,该软件有三类 用户:管理员、教师和学生,其分别具有如下功能
管理员:
1. 创建计算机专业课程信息
2. 添加计算机专业课程信息
3. 删除计算机专业课程信息
4. 统计计算机专业开设课程的总数
5. 查询每门课程修课人数
6. 浏览计算机专业的课程信息
教师:
1. 查询自己带的课程信息
2. 查询自己带的班级学生信息
3. 输入课程成绩
4. 修改课程成绩
5. 统计课程 90 分以上的人数、80\~90 分的人数、60\~80 分的人数、60 分以下的人数
学生:
1. 查询课程信息
2. 报名课程学习
3. 取消课程学习
4. 查询课程成绩
5. 浏览所有课程信息
其中,课程信息至少包含:课程号、课程名、课程的学分、任课教师、上课时间、上课地点、考试成绩;
学生信息至少包含:学号、姓名、联系方式。
## 项目设计
### 数据结构
通过分析系统功能,我们确定涉及到的操作对象主要有三类:用户(User)、课程(Course)和学生选课(CourseSelection)。
对于用户(User)实体,我们选择使用顺序结构来组织各个属性字段,并进一步采用有序集合来存储多个用户实体的数据。具体的逻辑结构形式如图1-2-1所示:
![img.png](images/img.png)
在课程(Course)实体方面,我们也采用顺序数据结构以组织各个属性字段。值得注意的是,其中的“开课教师”属性字段专门用于存储对应的教师用户实体。与用户实体类似,我们也采用有序集合数据结构来汇聚和存储多个课程实体。该逻辑结构的具体形式如图1-2-2所展示。
![img_1.png](images/img_1.png)
在学生选课(CourseSelection)实体的设计方面,我们沿用与课程(Course)实体类似的数据存储结构。在“选课学生”和“选课课程”属性字段中,我们分别存储对应的学生和课程实体。该逻辑结构的具体形式如图1-2-3所示。
![img_2.png](images/img_2.png)
这种设计方案便于实施各种查询和修改操作,同时也为将来可能的功能扩展提供了灵活性。
为了实现多样的查询功能,包括基于教师身份查询所教授课程,以及基于学生身份查询已选课程等,同时优化代码的可重用性与可维护性,我们采取了一种策略,即将用于查询的数据结构(称为通用索引,Index)与各个实体类型(User、Course、CourseSelection)进行解耦。在这里,我们以实体的id作为主键,其他必要信息作为次要键,并通过通用索引创建多级索引。索引同样采用顺序结构组织各个属性字段,并使用有序集合存储多个索引的实体数据。具体的逻辑结构形式如图1-2-4所示。
![img_3.png](images/img_3.png)
在前述通用索引结构的基础上,我们设计了一系列专门的索引,以满足系统不同方面的需求。具体的索引结构、功能以及所存储的键(Key)和值(Value)的类型如表1-2-1所示。
| 索引名称 | 键(Key) | 链表内值(Value) | 功能描述 |
|---------------------------------|--------------------------------|-------------------|---------------------------------|
| user_id_Index | 用户ID | 对应的用户结构体 | 便于通过用户ID快速检索用户信息,同时缓存从文件加载的数据 |
| user_name_Index | 用户姓名的哈希值 | 用户ID | 通过用户姓名的哈希值检索其ID |
| user_empId_Index | 用户学工号的哈希值 | 用户ID | 通过学工号的哈希值检索用户ID |
| user_file_Index | 用户ID | 存于系统文件中的用户数据文件名 | 映射用户ID与其在文件系统中的数据文件 |
| course_id_Index | 课程ID | 对应的课程结构体 | 便于通过课程ID快速检索课程信息,同时缓存从文件加载的数据 |
| course_name_Index | 课程名称的哈希值 | 课程ID | 通过课程名称的哈希值检索其ID |
| course_teacherId_Index | 教师ID | 教师所教授的课程ID | 便于查找教师负责的所有课程 |
| course_file_Index | 课程ID | 存于文件系统中的课程数据文件名 | 映射课程ID与其在文件系统中的数据文件 |
| selection_id_Index | 选课信息ID | 对应选课信息结构体 | 便于通过选课信息ID快速检索选课信息,同时缓存从文件加载的数据 |
| selection_userId_Index | 用户ID | 用户所选课程ID | 检索某个用户选择的所有课程 |
| selection_courseId_Index | 课程ID | 课程对应选课用户ID | 查找选修某一课程的所有用户 |
| selection_userId_courseId_Index | 用户ID与课程ID组合后计算的哈希值 | 选课信息ID | 通过用户ID和课程ID组合进行复合检索 |
| selection_file_Index | 选课信息ID | 存于文件系统中的选课信息数据文件名 | 映射选课信息ID与其在文件系统中的数据文件 |
| global_counter_Index | 对应不同数据,例如user、course、selection | 统计每个类型的数据包含多少条数据 | 用于全局计数,如统计不同实体类型的数据条数等 |
在存储操作对象时,目标是对各操作对象信息的各字段进行快速而准确的查询与修改。为实现该目标,我们选择使用结构体(Struct)的方式来对各实体进行存储。
用户(User)、课程(Course)与选课信息(CourseSelection)的结构体如下方代码所示:
```c
// 用户
typedef struct {
int64 id; // 用户ID
char name[21], // 用户姓名
passwd[65], // 密码
empId[21]; // 学工号
int role; // 用户角色 0-学生 1-教师 2-管理员
char contact[201]; // 联系方式
int64 lastLoginTime; // 最后一次登录时间戳
} User;
// 课程
typedef struct {
int64 id; // 课程ID/课程号
char courseName[101],// 课程名称
description[501]; // 课程描述
int64 teacherId; // 任课老师ID
User *teacher; // 任课老师
int type, // 课程类型:0-必修 1-选修 2-公选 3-辅修
weekStart, // 开课周
weekEnd, // 结课周
currentMembers, // 当前报名人数
maxMembers; // 最大可报名人数
char location[101]; // 上课地点
double points; // 学分
int schedule[7][13]; // 每星期课程安排
} Course;
// 选课信息
typedef struct {
int64 id; // 选课ID
int64 studentId; // 学生ID
User *student; // 学生信息
int64 courseId; // 课程ID
Course *course; // 课程信息
int64 selectionTime; // 选择该课程的时间
int64 score; // 成绩
} CourseSelection;
```
考虑到对内存空间的高效利用,我们选择采用链式存储结构来存储多个操作对象。链式存储结构在存储�