目录
1.问题定义
本次课程设计要求协助中国大学生计算机设计大赛江苏省组委会,设计一款赛事管理系统,实现赛务相关的数据管理及信息服务,该系统能够为省级赛事管理解决以下问题:
(1)能够管理各参赛队的基本信息(包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项(参见大赛官网jsjds.blcu.edu.cn);包括增加、删除、修改参赛队伍的信息。
(2)从team.txt中读取参赛队伍的基本信息,实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。
(3) 能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队),即,根据提示输入参赛学校名称(赛事类别),若查找成功,输出该学校参赛的(该赛事类别的)所有团队的基本信息,输出的参赛团队按赛事类别有序输出。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)
(4)为省赛现场设计一个决赛叫号系统。所有参赛队按赛事组织文件中的赛事类别分到9个决赛室,决赛室按顺序叫号,被叫号参赛队进场,比赛结束后,下一参赛队才能进赛场。请模拟决赛叫号系统,演示省赛现场各决赛室的参赛队进场情况。(模拟时,各参赛队进场比赛时间可设为0.5秒)
(5)赛事系统为参赛者提供赛地的校园导游程序。为参赛者提供各种路径导航的查询服务。以我校长山校区提供比赛场地为例,(请为参赛者提供不少于10个目标地的导航。可为参赛者提供校园地图中任意目标地(建筑物)相关信息的查询;提供图中任意目标地(建筑物)的问路查询,即查询任意两个目的地(建筑物)之间的一条最短的简单路径。
2.问题分析
(1)该系统需要对参赛队伍的基本信息进行管理,包括参赛队编号、参赛作品名称、参赛学校、赛事类别、参赛者、指导老师等信息。同时,还需要具备增加、删除、修改参赛队伍信息的功能。因此,该系统需要具备以下基本功能:
添加参赛队伍信息,删除参赛队伍信息,修改参赛队伍信息,查询参赛队伍信息。
(2)问题要求从team.txt文件中读取参赛队伍的基本信息,并将其插入到二叉排序树中。
文件读写:需要了解如何打开文件、读取文件、关闭文件等相关操作。读取team.txt文件时,可以使用C++的文件输入输出流(fstream)类来实现。二叉排序树:需要了解二叉排序树的定义、插入节点、查找节点等操作,以及如何计算平均查找长度ASL。
(3)该模块需要实现按参赛学校查询参赛队伍信息的功能,支持根据赛事类别、参赛学校等条件进行查询,并按照赛事类别有序输出查询结果。为了实现该模块,可以采用链表等数据结构进行存储参赛队伍信息,并根据需要设计相应的排序算法(如选择排序、插入排序、希尔排序、归并排序、堆排序等)实现按照赛事类别有序输出查询结果的功能。
(4)为省赛现场设计一个决赛叫号系统,可以使用队列来实现。具体来说,为每个决赛室创建一个队列,参赛队依次加入到相应的队列中。然后按照顺序依次从每个队列中取出参赛队,并展示其进场情况。
(5)为参赛者提供赛地的校园导游程序,可以使用校园地图和路径导航算法来实现。具体来说,可以使用图论中的最短路径算法,如Dijkstra算法。来查询任意两个目标地(建筑物)之间的最短路径,并将路径显示在地图上,为参赛者提供导航服务。同时,还可以提供校园地图中任意目标地(建筑物)相关信息的查询功能,如建筑物名称、位置、功能等信息。
3.算法设计
该系统使用C++语言进行开发,并采用文件进行数据存储。系统包含一个主函数和一个参赛队伍信息类。主函数中包含添加、删除、修改和查询参赛队伍信息的函数,参赛队伍信息类中包含参赛队伍的基本信息。以下是类的设计:
参赛队伍信息类:
class Team {
private:
string teamNumber; // 参赛队编号
string projectName;// 参赛作品名称
string schoolName; // 参赛学校
string gameType; // 赛事类别
string participants; // 参赛者
string instructor; // 指导老师
public:
// 构造函数
Team(string num, string project, string school, string type, string part, string ins) {
teamNumber = num;
projectName = project;
schoolName = school;
gameType = type;
participants = part;
instructor = ins;
}
// 获取参赛队编号
string getTeamNumber() const {
return teamNumber;
}
// 获取参赛作品名称
string getProjectName() const {
return projectName;
}
// 获取参赛学校
string getSchoolName() const {
return schoolName;
}
// 获取赛事类别
string getGameType() const {
return gameType;
}
// 获取参赛者
string getParticipants() const {
return participants;
}
// 获取指导老师
string getInstructor() const {
return instructor;
}
// 设置参赛队编号
void setTeamNumber(string num) {
teamNumber = num;
}
// 设置参赛作品名称
void setProjectName(string project) {
projectName = project;
}
// 设置参赛学校
void setSchoolName(string school) {
schoolName = school;
}
// 设置赛事类别
void setGameType(string type) {
gameType = type;
}
// 设置参赛者
void setParticipants(string part) {
participants = part;
}
// 设置指导老师
void setInstructor(string ins) {
instructor = ins;
}
};
添加参赛队伍信息函数:
void addTeamInfo(vector<Team>& teams) {
string num, project, school, type, part, ins;
cout << "请输入参赛队编号:";
cin >> num;
cout << "请输入参赛作品名称:";
cin >> project;
cout << "请输入参赛学校:";
cin >> school;
cout << "请输入赛事类别:";
cin >> type;
cout << "请输入参赛者:";
cin >> part;
删除参赛队伍信息函数:
void deleteTeamInfo(vector<Team>& teams, string num) {
for (int i = 0; i < teams.size(); i++) {
if (teams[i].getTeamNumber() == num) {
teams.erase(teams.begin() + i);
cout << "删除成功!" << endl;
return;
}
}
cout << "未找到该参赛队伍信息!" << endl;
}
void modifyTeamInfo(vector<Team>& teams, string num) {
for (int i = 0; i < teams.size(); i++) {
if (teams[i].getTeamNumber() == num) {
string project, school, type, part, ins;
cout << "请输入新的参赛作品名称:";
cin >> project;
cout << "请输入新的参赛学校:";
cin >> school;
cout << "请输入新的赛事类别:";
cin >> type;
cout << "请输入新的参赛者:";
cin >> part;
cout << "请输入新的指导老师:";
cin >> ins;
teams[i].setProjectName(project);
teams[i].setSchoolName(school);
teams[i].setGameType(type);
teams[i].setParticipants(part);
teams[i].setInstructor(ins);
cout << "修改成功!" << endl;
return;
}
}
cout << "未找到该参赛队伍信息!" << endl;
}
定义二叉排序树节点的结构体:
struct TreeNode {
Team data; // 节点存储的参赛队伍信息
TreeNode* left; // 左子树指针
TreeNode* right; // 右子树指针
};
定义二叉排序树结构体:
struct BST {
TreeNode* root; // 根节点指针
};
读取文件并插入节点:
void insertNode(BST& bst, Team team) {
TreeNode* newNode = new TreeNode;
newNode->data = team;
newNode->left = NULL;
newNode->right = NULL;
if (bst.root == NULL) {
bst.root = newNode;
return;
}
TreeNode* curNode = bst.root;
while (curNode != NULL) {
if (team.id < curNode->data.id) {
if (curNode->left == NULL) {
curNode->left = newNode;
return;
} else {
curNode= curNode->left;
}
} else {
if (curNode->right == NULL) {
curNode->right = newNode;
return;
} else {
curNode = curNode->right;
}
}
}
}
实现查找函数:
bool searchNode(TreeNode* curNode, int id, int& count, Team& team) {
if (curNode == NULL) {
return false;
}
count++;
if (curNode->data.id == id) {
team = curNode->data;
return true;
} else if (curNode->data.id > id) {
return searchNode(curNode->left, id, count, team);
} else {
return searchNode(curNode->right, id, count, team);
}
}
void search(BST bst, int id) {
int count = 0;
Team team;
if (searchNode(bst.root, id, count, team)) {
cout << "参赛作品名称:" << team.name << endl;
cout << "参赛学校:" << team.school << endl;
cout << "赛事类别:" << team.category << endl;
cout << "参赛者信息:" << team.contestant << endl;
cout << "指导老师信息:" << team.teacher <<endl;
cout << "平均查找长度ASL:" << (double)count << endl;
} else {
cout << "查找失败!" << endl;
}
}
按参赛学校查询参赛团队或根据赛事类别查询参赛团队
为了实现按参赛学校查询参赛团队或根据赛事类别查询参赛团队,需要在参赛队伍管理类中添加两个查询函数,分别用于按参赛学校和赛事类别查询参赛队伍,并按照赛事类别有序输出结果。
class TeamManager {
private:
std::vector<Team> teams;
std::vector<Score> scores;
public:
// 省略添加、删除、修改和查询参赛队伍信息和成绩等操作
// 按参赛学校查询参赛队伍
std::vector<Team> queryTeamBySchool(const std::string& schoolName) const {
std::vector<Team> result;
for (const auto& t : teams) {
if (t.schoolName == schoolName) {
result.push_back(t);
}
}
std::sort(result.begin(), result.end(), [](const Team& t1, const Team& t2) {
return t1.gameType < t2.gameType;
});
return result;
}
// 根据赛事类别查询参赛队伍
std::vector<Team> queryTeamByGameType(Team::GameType gameType) const {
std::vector<Team> result;
for (const auto& t : teams) {
if (t.gameType == gameType) {
result.push_back(t);
}
}
std::sort(result.begin(), result.end(), [](const Team& t1, const Team& t2) {
return t1.schoolName < t2.schoolName;
});
return result;
}
};
其中,按参赛学校查询参赛队伍的函数中,使用了std::sort()标准库函数对结果进行排序,排序方式是按照赛事类别升序排列。而根据赛事类别查询参赛队伍的函数中,使用了std::sort()标准库函数对结果进行排序,排序方式是按照参赛学校名称升序排列。
叫号系统
void eventCate_separate(vector<Team> team)
{
vector<string> teameventCate;
for (int i = 0; i < team.size(); i++)
{
if (std::find(teameventCate.begin(), teameventCate.end(), team[i].geteventCate()) == teameventCate.end())
{
teameventCate.push_back(team[i].geteventCate());
}
}
for (int i = 0; i < teameventCate.size(); i++)
{
for (int m = 0; m < team.size(); m++)
{
if (i < 3)
{
if (teameventCate[i] == team[m].geteventCate())
{
a1.push_back(team[m]);
}
}
if (i >= 3 && i <= 5)
{
if (teameventCate[i] == team[m].geteventCate())
{
a2.push_back(team[m]);
}
}
if (i >= 6 && i <= 8)
{
if (teameventCate[i] == team[m].geteventCate())
{
a3.push_back(team[m]);
}
}
if (i >= 9 && i <= 11)
{
if (teameventCate[i] == team[m].geteventCate())
{
a4.push_back(team[m]);
}
}
if (i >= 12 && i <= 14)
{
if (teameventCate[i] == team[m].geteventCate())
{
a5.push_back(team[m]);
}
}
if (i >= 15 && i <= 18)
{
if (teameventCate[i] == team[m].geteventCate())
{
a6.push_back(team[m]);
}
}
if (i >= 19 && i <= 22)
{
if (teameventCate[i] == team[m].geteventCate())
{
a7.push_back(team[m]);
}
}
if (i >= 23 && i <= 26)
{
if (teameventCate[i] == team[m].geteventCate())
{
a8.push_back(team[m]);
}
}
if (i >= 27 && i < teameventCate.size())
{
if (teameventCate[i] == team[m].geteventCate())
{
a9.push_back(team[m]);
}
}
}
}
}
导航系统
// 最短路径算法
vector<int> dijkstra(int start) {
vector<int> distances(nodes.size(), INT_MAX);
distances[start] = 0;
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
pq.push(make_pair(0, start));
while (!pq.empty()) {
auto top = pq.top();
pq.pop();
int node = top.second;
int distance = top.first;
if (distance > distances[node]) {
continue;
}
for (auto edge : nodes[node].edges) {
int nextNode = edge.to;
int nextDistance = distance + edge.cost;
if (nextDistance < distances[nextNode]) {
distances[nextNode] = nextDistance;
paths[nextNode] = node;
pq.push(make_pair(nextDistance, nextNode));
}
}
}
return distances;
}