中国大学生计算机设计大赛省级赛事管理系统
中国大学生计算机设计大赛是我国高校面向本科生的计算机应用设计大赛,大赛旨在激发学生学习计算机知识和技能的兴趣与潜能,提高学生运用信息技术解决实际问题的综合能力。通过大赛这种计算机教学实践形式,可展示师生的教与学成果,最终以赛促学,以赛促教,以赛促创。该赛事在历届学生中影响力较大,参与者众多,请结合2021届省赛参赛的数据,借助数据结构课程所学的相关知识,通过对数据的处理和分析,全面了解赛事组织及管理的体系,以及数据结构设计及数据处理在信息管理系统中应用的重要性。赛事相关数据存储在文本文件和excel文件中,相应的文件信息说明如表1所示。其中,各个文件中不同的数据项之间均使用#分隔,图1中给出了文件team.txt中参赛信息的对应数据示
【问题描述】
要求协助中国大学生计算机设计大赛江苏省组委会,设计一款赛事管理系统,实现赛务相关的数据管理及信息服务,该系统能够为省级赛事管理解决以下问题:
(1)从team.txt中读取参赛队伍的基本信息,能够管理各参赛队的基本信息(包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项(参见大赛官网jsjds.blcu.edu.cn);包括增加、删除、修改参赛队伍的信息。
(2)实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。请输出ASL的计算表达式和结果值。
(3)能够提供按参赛学校查询参赛团队,根据提示输入参赛学校名称,若查找成功,输出该学校参赛的所有团队的基本信息,输出的参赛团队需有序输出(按参赛队编号)。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)
(4)为省赛现场设计一个决赛叫号系统。所有参赛队按赛事组织文件中的赛事类别分到9个决赛室,决赛室按顺序叫号,被叫号参赛队进场,比赛结束后,下一参赛队才能进赛场。请模拟决赛叫号系统,演示省赛现场各决赛室的参赛队进场情况。(模拟时,各参赛队进场比赛时间可设为0.5秒)
(5)赛事系统为参赛者提供赛地的校园导游程序。为参赛者提供各种路径导航的查询服务。以我校长山校区提供比赛场地为例,(请为参赛者提供不少于10个目标地的导航。可为参赛者提供校园地图中任意目标地(建筑物)相关信息的查询;提供图中任意目标地(建筑物)的问路查询,即查询任意两个目的地(建筑物)之间的一条最短的简单路径。
1 参赛队伍管理
从team.txt中读取参赛队伍的基本信息,能够管理各参赛队的基本信息(包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项(参见大赛官网jsjds.blcu.edu.cn);包括增加、删除、修改参赛队伍的信息。
-
- 问题分析
题目要求:能够管理各参赛队的基本信息(包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项(参见大赛官网);包括增加、删除、修改参赛队伍的信息。
需求分析:从team.txt文件中读取参赛队伍的基本信息。
实现增加参赛队伍信息功能。
实现删除参赛队伍信息功能。
实现修改参赛队伍信息功能。
2 基于二叉排序树的查找
实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。请输出ASL的计算表达式和结果值。
2.1 问题分析
题目要求:根据参赛队伍的基本信息,实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。
需求分析
输入:参赛队编号。
输出:如果查找成功,则输出该队伍的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时输出查找成功时的平均查找长度(ASL)。如果查找失败,则输出"查找失败!"。
3 参赛队伍查询
能够提供按参赛学校查询参赛团队,根据提示输入参赛学校名称,若查找成功,输出该学校参赛的所有团队的基本信息,输出的参赛团队需有序输出(按参赛队编号)。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)
3.1 问题分析
题目要求:能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队),即,根据提示输入参赛学校名称(赛事类别),若查找成功,输出该学校参赛的(该赛事类别的)所有团队的基本信息,输出的参赛团队按赛事类别有序输出。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)
需求分析:
用户需要根据参赛学校名称或赛事类别查询参赛团队的基本信息,并按照赛事类别对查询结果进行排序。
查询成功时,需要输出该学校参赛的指定赛事类别的所有团队的基本信息,并按照赛事类别有序输出。
可以使用插入排序算法进行排序,选择插入排序的原因可以是其简单易实现且适用于小规模数据的排序。
4 决赛叫号模拟
为省赛现场设计一个决赛叫号系统。所有参赛队按赛事组织文件中的赛事类别分到9个决赛室,决赛室按顺序叫号,被叫号参赛队进场,比赛结束后,下一参赛队才能进赛场。请模拟决赛叫号系统,演示省赛现场各决赛室的参赛队进场情况。(模拟时,各参赛队进场比赛时间可设为0.5秒)
4.1问题分析
定义一个列表或队列,存储每个参赛队的信息和状态,包括队伍名称、所属赛事类别、当前状态(等待/已进场)等。
根据赛事组织文件中的赛事类别,将所有参赛队分配到对应的决赛室。
定义一个主循环,在每个循环周期中,检查每个决赛室的状态。
等待一段时间,模拟队伍进场比赛的过程。
待当前队伍比赛结束后,再从等待队列中取出下一个队伍,当所有队伍都已经进场比赛后,程序退出主循环。
需要注意的问题:需要保证并发安全,即多个决赛室之间不能相互干扰。需要设置适当的等待时间,以便模拟队伍进场比赛的过程。
5 校园导游咨询
赛事系统为参赛者提供赛地的校园导游程序。为参赛者提供各种路径导航的查询服务。以我校长山校区提供比赛场地为例,(请为参赛者提供不少于10个目标地的导航。可为参赛者提供校园地图中任意目标地(建筑物)相关信息的查询;提供图中任意目标地(建筑物)的问路查询,即查询任意两个目的地(建筑物)之间的一条最短的简单路径。
5.1 问题分析
这显然是一个图论问题,而且校园内道路一般是双向通行的,所以这是一个无向图。对于图的存储结构而言,图中各个景点的存储结构有邻接表和邻接矩阵两种存储结构,考虑到顶点个数少于50个,所以邻接表和邻接矩阵的复杂度相同。本题中选择使用邻接矩阵来表示图。
任务中要求求解出图中景点的问路查询,即为给定两个源点,求解出两个顶点之间的最短路径。根据数据结构课程所学知识,有多种经典算法可以解决最短路径问题,包括Dijkstra算法,Floyd-Warshell算法,Bellman-Ford算法和深度优先遍历。不同是算法有不同的算法复杂度,考虑到校园中道路没有负权边,即算法均可解决最短路径问题。
参考文献
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// 参赛队类
class ContestantTeam {
private:
string teamNo; // 参赛队编号
string workName; // 参赛作品名称
string school; // 参赛学校
string category; // 赛事类别
string* members; // 参赛者
string coach; // 指导老师
int numMembers; // 参赛成员数量
public:
ContestantTeam() {
members = NULL;
numMembers = 0;
}
~ContestantTeam() {
if (members != NULL) {
delete[] members;
}
}
void setTeamNo(string no) {
teamNo = no;
}
void setWorkName(string name) {
workName = name;
}
void setSchool(string schoolName) {
school = schoolName;
}
void setCategory(string categoryName) {
category = categoryName;
}
void addMember(string memberName) {
if (members == NULL) {
members = new string[1];
numMembers = 1;
}
else {
string* newMembers = new string[numMembers + 1];
for (int i = 0; i < numMembers; i++) {
newMembers[i] = members[i];
}
delete[] members;
members = newMembers;
numMembers++;
}
}
void setCoach(string coachName) {
coach = coachName;
}
string getTeamNo() {
return teamNo;
}
string getCategory() {
return category;
}
string getInfo() {
string result = "";
result += "参赛作品名称:" + workName + "\n";
result += "参赛学校:" + school + "\n";
result += "参赛者:";
for (int i = 0; i < numMembers; i++) {
result += members[i] + " ";
}
result += "\n";
result += "指导老师:" + coach + "\n";
return result;
}
};
// 二叉排序树节点类
class TreeNode {
public:
ContestantTeam* team;
TreeNode* left;
TreeNode* right;
TreeNode() {
team = NULL;
left = NULL;
right = NULL;
}
~TreeNode() {
delete team;
}
};
// 二叉排序树类
class BinarySearchTree {
private:
TreeNode* root;
int numNodes;
int numVisits;
int totalDepth;
public:
BinarySearchTree() {
root = NULL;
numNodes = 0;
numVisits = 0;
totalDepth = 0;
}
~BinarySearchTree() {
clear(root);
}
void clear(TreeNode* node) {
if (node != NULL) {
clear(node->left);
clear(node->right);
delete node;
}
}
void insert(ContestantTeam* team) {
TreeNode* newNode = new TreeNode();
newNode->team = team;
if (root == NULL) { // 树为空
root = newNode;
}
else {
TreeNode* currentNode = root;
while (true) {
if (team->getTeamNo() < currentNode->team->getTeamNo()) {
if (currentNode->left == NULL) {
currentNode->left = newNode;
break;
}
else {
currentNode = currentNode->left;
}
}
else {
if (currentNode->right == NULL) {
currentNode->right = newNode;
break;
}
else {
currentNode = currentNode->right;
}
}
}
}
numNodes++;
}
bool search(string teamNo, string& result) {
numVisits = 0;
totalDepth = 0;
TreeNode* currentNode = root;
while (currentNode != NULL) {
numVisits++;
totalDepth += 1;
if (teamNo < currentNode->team->getTeamNo()) {
currentNode = currentNode->left;
}
else if (teamNo > currentNode->team->getTeamNo()) {
currentNode = currentNode->right;
}
else { // 找到了
result = currentNode->team->getInfo();
return true;
}
}
return false;
}
int getASL() {
if (numVisits == 0) {
return 0;
}
else {
return totalDepth / numVisits + 1;
}
}
};// 主程序
int main() {
BinarySearchTree* bst = new BinarySearchTree();
// 从文件中读取参赛队信息
ifstream infile("team.txt");
string line;
while (getline(infile, line)) {
ContestantTeam* team = new ContestantTeam();
team->setTeamNo(line.substr(0, 3));
team->setWorkName(line.substr(4, 20));
team->setSchool(line.substr(25, 20));
team->setCategory(line.substr(46, 11));
team->addMember(line.substr(59, 10));
team->addMember(line.substr(70, 10));
team->setCoach(line.substr(81, 10));
bst->insert(team);
}
// 用户输入
while (true) {
cout << "请选择操作:" << endl;
cout << "1. 增加参赛队伍" << endl;
cout << "2. 删除参赛队伍" << endl;
cout << "3. 修改参赛队伍" << endl;
cout << "4. 查找参赛队伍" << endl;
cout << "5. 退出" << endl;
int choice;
cin >> choice;
if (choice == 1) { // 增加参赛队伍
ContestantTeam* team = new ContestantTeam();
cout << "请输入参赛队编号:" << endl;
string teamNo;
cin >> teamNo;
team->setTeamNo(teamNo);
cout << "请输入参赛作品名称:" << endl;
string workName;
cin >> workName;
team->setWorkName(workName);
cout << "请输入参赛学校:" << endl;
string school;
cin >> school;
team->setSchool(school);
cout << "请输入赛事类别(共11项):" << endl;
string category;
cin >> category;
team->setCategory(category);
cout << "请输入参赛者(每行一个):" << endl;
while (true) {
string memberName;
cin >> memberName;
if (memberName == "END") {
break;
}
team->addMember(memberName);
}
cout << "请输入指导老师:" << endl;
string coach;
cin >> coach;
team->setCoach(coach);
bst->insert(team);
cout << "参赛队伍添加成功!" << endl;
}
else if (choice == 2) { // 删除参赛队伍
cout << "请输入参赛队编号:" << endl;
string teamNo;
cin >> teamNo;
string result;
if (bst->search(teamNo, result)) {
cout << "查找到参赛队伍:" << endl;
cout << result << endl;
cout << "是否确认删除该参赛队伍?(Y/N)" << endl;
char confirm;
cin >> confirm;
if (confirm == 'Y' || confirm == 'y') {
// 删除节点
}
}
else {
cout << "查找失败!" << endl;
}
}
else if (choice == 3) { // 修改参赛队伍
cout << "请输入参赛队编号:" << endl;
string teamNo;
cin >> teamNo;
string result;
if (bst->search(teamNo, result)) {
cout << "查找到参赛队伍:" << endl;
cout << result << endl;
cout << "请输入要修改的属性名(team_no、work_name、school、category、members、coach):" << endl;
string propertyName;
cin >> propertyName;
if (propertyName == "team_no") {
// 修改team_no
}
else if (propertyName == "work_name") {
// 修改work_name
}
else if (propertyName == "school") {
// 修改school
}
else if (propertyName == "category") {
// 修改category
}
else if (propertyName == "members") {
// 修改members
}
else if (propertyName == "coach") {
// 修改coach
}
else {
cout << "输入的属性名不正确!" << endl;
}
}
else {
cout << "查找失败!" << endl;
}
}
else if (choice == 4) { // 查找参赛队伍
cout << "请输入参赛队编号:" << endl;
string teamNo;
cin >> teamNo;
string result;
if (bst->search(teamNo, result)) {
cout << "查找成功!" << endl;
cout << result << endl;
cout << "平均查找长度ASL:" << bst->getASL() << endl;
}
else {
cout << "查找失败!" << endl;
}
}
else if (choice == 5) { // 退出
break;
}
else {
cout << "输入无效,请重新输入!" << endl;
}
}
delete bst;
return 0;
}
《数据结构与算法分析》(作者:Mark Allen Weiss)
《数据库系统概论》(作者:Abraham Silberschatz)