1 问题描述:
本次课程设计要求协助中国大学生计算机设计大赛江苏省组委会,设计一款赛事管理系统,实现赛务相关的数据管理及信息服务,该系统能够为省级赛事管理解决以下问题:
- 能够管理各参赛队的基本信息(包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项;包括增加、删除、修改参赛队伍的信息。
- 从team.txt中读取参赛队伍的基本信息,实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。
- 能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队),即,根据提示输入参赛学校名称(赛事类别),若查找成功,输出该学校参赛的(该赛事类别的)所有团队的基本信息,输出的参赛团队按赛事类别有序输出。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)
- 为省赛现场设计一个决赛叫号系统。所有参赛队按赛事组织文件中的赛事类别分到9个决赛室,决赛室按顺序叫号,被叫号参赛队进场,比赛结束后,下一参赛队才能进赛场。请模拟决赛叫号系统,演示省赛现场各决赛室的参赛队进场情况。(模拟时,要能直观展示叫号顺序与进场秩序一致)
- 赛事系统为参赛者提供赛地的校园导游程序,为参赛者提供各种路径导航的查询服务。以我校长山校区提供比赛场地为例,(请为参赛者提供不少于10个目标地的导航。可为参赛者提供校园地图中任意目标地(建筑物)相关信息的查询;提供任意两个目标地(建筑物)的导航查询,即查询任意两个目的地(建筑物)之间的一条最短路径。
2、问题分析
1:管理各参赛队的基本信息,增删修改参赛队伍的信息。可以构建一个team结构体,利用函数读取文本中的信息,将各team放入二叉树中。
// 定义参赛队伍结构体 typedef struct { char teamID[20]; char projectName[100]; char school[50]; char category[20]; char participant[50]; char advisor[50]; char entrance[4]; } Team;
/*函数声明*/ // 从文件中读取参赛队伍的基本信息,构建二叉排序树 BSTNode* buildBSTFromFile(const char* filename); // 在二叉排序树中插入参赛队伍 void insertTeam(BSTNode** root, Team team); // 删除参赛队伍 void deleteTeam(BSTNode** root, char* teamID); // 修改参赛队伍 void modifyTeam(BSTNode* root, char* teamID); // 在二叉排序树中查找参赛队伍 BSTNode* searchTeam(BSTNode* root, char* teamID, int* asl); // 打印参赛队伍的基本信息 void printTeamInfo(Team team); // 打印比赛时,参赛队伍的基本信息 void printTeamInfoBattle(Team* team); // *对排序 void sortByCategory(BSTNode* root, Team* entrance, char* category); // 销毁二叉排序树 void destroyBST(BSTNode* root);
由于第2问有关二叉排序树的查找,所以构建一个二叉排序树的结构体
// 定义二叉排序树结点结构体 typedef struct BSTNode { Team team; struct BSTNode* left; struct BSTNode* right; } BSTNode;
2从team.txt中读取信息,实现基于二叉树的查找
// 从文件中读取参赛队伍的基本信息,构建二叉排序树 BSTNode* root = buildBSTFromFile("team.txt"); // 定义二叉排序树结点结构体 typedef struct BSTNode { Team team; struct BSTNode* left; struct BSTNode* right; } BSTNode;
STNode* searchTeam(BSTNode* root, char* teamID, int* asl) { if (root == NULL) { *asl = 0; return NULL; } BSTNode* current = root; int count = 0; // 在二叉排序树中查找指定的参赛队伍 while (current != NULL) { count++; int cmp = strcmp(teamID, current->team.teamID); if (cmp == 0) { *asl = count; return current; } if (cmp < 0) { current = current->left; } else { current = current->right; } } *asl = count; return NULL; }
- 首先,判断给定的根节点是否为空。如果为空,则返回 NULL 并将平均查找长度设置为 0。
- 如果给定的根节点不为空,则从该节点开始按照二叉排序树的查找规则进行查找。具体来说,每次比较查询关键字与当前节点存储的关键字(这里是参赛队伍的 ID)的大小,如果相等则说明已经找到目标节点,返回该节点指针并将查找的次数作为平均查找长度。
- 如果查询关键字小于当前节点的关键字,则向当前节点的左子树查找;否则向右子树查找,直到找到目标节点或遇到空节点为止。
- 最终,如果未能找到目标节点,则返回 NULL 并将查找的次数设置为平均查找长度。
3赛事类别查找参赛队伍
void printTeamsByCategory(BSTNode* root, char* category) { if (root == NULL) { //printf("没有找到相关的参赛队伍!\n"); return; } if (root->left != NULL) { printTeamsByCategory(root->left, category); } if (strcmp(root->team.category, category) == 0) { printTeamInfo(root->team); } printTeamsByCategory(root->right, category); }
- 首先,判断给定的根节点是否为空。如果为空,则直接返回。
- 如果给定的根节点不为空,就先递归地查找其左子树,以便按照关键字的大小顺序遍历整个树。
- 如果当前节点存储的参赛队伍所属类别和指定的查询类别相同,则输出该参赛队伍的信息。具体来说,调用
printTeamInfo()
函数将该参赛队伍的信息打印到控制台上。- 最后,再递归地查找当前节点的右子树,继续按照关键字遍历二叉排序树。
4决赛摇号系统
const char* TypesAndEntrances[][2] = { {"大数据实践", "A"}, {"信息图形设计", "A"}, {"动态信息影像(MG动画)", "A"}, {"交互信息设计", "A"}, {"数据可视化", "A"}, {"人工智能实践赛", "B"}, {"Web应用与开发", "B"}, {"管理信息系统", "B"}, {"算法设计与应用", "B"}, {"移动应用开发", "B"}, {"医药卫生", "C"}, {"数字生活", "C"}, {"运动健身", "C"}, {"城市管理", "D"}, {"行业应用", "D"}, {"动画", "E"}, {"纪录片", "E"}, {"数字短片", "E"}, {"微电影", "E"}, {"新媒体漫画", "F"}, {"产品设计", "F"}, {"环境设计", "F"}, {"平面设计", "F"}, {"交互媒体设计", "G"}, {"游戏设计", "G"}, {"虚拟现实VR与增强现实AR", "G"}, {"汉语言文学", "I"}, {"计算机基础与应用类课程微课", "I"}, {"虚拟实验平台", "I"}, {"中、小学数学或自然科学课程微课", "I"} }; //延时函数 void delay(int milliseconds) { clock_t start_time = clock(); while (clock() < start_time + milliseconds) ; } // 根据类型进行决赛分组 void sortByCategory(BSTNode* root, Team* entrance[], char* type) { if (root == NULL) { return; } if (root->left != NULL) { sortByCategory(root->left,entrance, type); } if (strcmp(root->team.entrance, type) == 0) { entrance[entranceCount] = &root->team; entranceCount++; } sortByCategory(root->right,entrance, type); }
- 函数
sortByCategory()
实现参赛队伍按照比赛入口进行分组。具体来说,该函数的参数包括一个指向根节点的指针root
,一个存储参赛队伍信息的数组entrance[]
,以及一个指向比赛入口字符串的指针type
。函数首先使用递归的方式遍历二叉排序树,将符合指定比赛入口的参赛队伍信息存储到entrance[]
数组中,并过entranceCount
记录已经存储的队伍数量。
5地图导航系统,设置了一个简易的地图查看系统
#include<iostream> #include "stdio.h" #include<iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> using namespace std; using namespace cv; int main(int argc, char** argv) { int a; cout << "欢迎使用地图导航系统" << endl; cout << "江科大地图a,请按1" << endl; cout << "江科大地图b,请按2" << endl; cin >> a; if (a == 1) { Mat img = imread("C:\\Users\\lenovo\\Desktop\\数据结构课程设计\\江科大地图a.jpg"); namedWindow("1"); imshow("1", img); cv::waitKey(6000); } if (a == 2) { Mat img = imread("C:\\Users\\lenovo\\Desktop\\数据结构课程设计\\江科大地图b.jpg"); namedWindow("2"); imshow("2", img); cv::waitKey(6000); } return 0; }
【设计要求】
- 1)赛事数据要求存入文件(txt或excel)并能读入查询;
- 2)赛地目的地查询,需提供目的地(建筑物)名称、代号、简介、两地之间路径长度等信息;
- 3)输入数据形式和范围:赛事相关数据可从键盘输入,或自文件导入。
- 4)界面要求:交互设计要合理,每个功能可以设计菜单,用户根据提示,完成相关功能的要求。
-
#define _CRT_SECURE_NO_WARNINGS //避免VS报错 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> const char* TypesAndEntrances[][2] = { {"大数据实践", "A"}, {"信息图形设计", "A"}, {"动态信息影像(MG动画)", "A"}, {"交互信息设计", "B"}, {"数据可视化", "B"}, {"人工智能实践赛", "B"}, {"Web应用与开发", "C"}, {"管理信息系统", "C"}, {"算法设计与应用", "C"}, {"移动应用开发", "D"}, {"医药卫生", "D"}, {"行业应用", "D"}, {"数字生活", "E"}, {"运动健身", "E"}, {"城市管理", "E"}, {"动画", "F"}, {"纪录片", "F"}, {"数字短片", "F"}, {"微电影", "G"}, {"新媒体漫画", "G"}, {"产品设计", "G"}, {"环境设计", "H"}, {"平面设计", "H"}, {"交互媒体设计", "H"}, {"游戏设计", "I"}, {"虚拟现实VR与增强现实AR", "I"}, {"汉语言文学", "I"}, {"计算机基础与应用类课程微课", "G"}, {"虚拟实验平台", "F"}, {"中、小学数学或自然科学课程微课", "E"} }; //延时函数 void delay(int milliseconds) { clock_t start_time = clock(); while (clock() < start_time + milliseconds) ; } // 定义参赛队伍结构体 typedef struct { char teamID[20]; char projectName[100]; char school[50]; char category[20]; char participant[50]; char advisor[50]; char entrance[4]; } Team; // 定义二叉排序树结点结构体 typedef struct BSTNode { Team team; struct BSTNode* left; struct BSTNode* right; } BSTNode; /*函数声明*/ // 从文件中读取参赛队伍的基本信息,构建二叉排序树 BSTNode* buildBSTFromFile(const char* filename); // 在二叉排序树中插入参赛队伍 void insertTeam(BSTNode** root, Team team); // 删除参赛队伍 void deleteTeam(BSTNode** root, char* teamID); // 修改参赛队伍 void modifyTeam(BSTNode* root, char* teamID); // 在二叉排序树中查找参赛队伍 BSTNode* searchTeam(BSTNode* root, char* teamID, int* asl); // 打印参赛队伍的基本信息 void printTeamInfo(Team team); // 打印比赛时,参赛队伍的基本信息 void printTeamInfoBattle(Team* team); // 按参赛学校查询参赛队伍 void printTeamsBySchool(BSTNode* root, char* school); // 按赛事类别查询参赛队伍 void printTeamsByCategory(BSTNode* root, char* category); // *对排序 void sortByCategory(BSTNode* root, Team* entrance, char* category); // 销毁二叉排序树 void destroyBST(BSTNode* root); // 将每个节点写入文件 void updateFile(BSTNode* root, FILE* file) { if (root != NULL) { // 将左子树写入文件 updateFile(root->left, file); // 将当前节点的内容写入文件 fprintf(file, "%s\t#\t%s\t#\t%s\t#\t%s\t#\t%s\t#\t%s\n", root->team.teamID, root->team.projectName, root->team.school, root->team.category, root->team.participant, root->team.advisor); // 将右子树写入文件 updateFile(root->right, file); } } // 打开文件,执行上面的递归函数 void updata(BSTNode* root) { // 打开文件进行内容更新 FILE* filez = fopen("team.txt", "w"); if (filez == NULL) { printf("无法打开文件 team.txt\n"); return; } // 遍历二叉排序树并将修改后的内容写入文件 updateFile(root, filez); // 关闭文件 fclose(filez); } // 最多地标点数和地标名称长度 #define MAX_BUILDINGS 10 #define MAX_NAME_LENGTH 20 // 定义地标的结构体 struct Building { int id; char name[MAX_NAME_LENGTH]; char description[100]; }; // 定义两地距离 struct Edge { int start; int end; int distance; }; struct Graph { struct Building buildings[MAX_BUILDINGS]; struct Edge edges[MAX_BUILDINGS * (MAX_BUILDINGS - 1) / 2]; int numBuildings; int numEdges; }; // 添加 void addBuilding(struct Graph* graph, int id, const char* name, const char* description); void addEdge(struct Graph* graph, int start, int end, int distance); int findBuildingId(struct Graph* graph, const char* name); void printBuildingInfo(struct Graph* graph, const char* name); void navigate(struct Graph* graph, const char* startName, const char* endName); int choice; //将按键值作为全局变量 int entranceCount = 0;//计数器 Team* entranceA[30]; Team* entranceB[30]; Team* entranceC[30]; Team* entranceD[30]; Team* entranceE[30]; Team* entranceF[30]; Team* entranceG[30]; Team* entranceH[30]; Team* entranceI[30]; int main() { BSTNode* root = buildBSTFromFile("team.txt"); // 从文件中读取参赛队伍的基本信息,构建二叉排序树 srand(time(NULL));// 设置随机数种子 // 定义变量 char teamID[20]; char school[50]; char category[20]; char siteA[20]; char siteB[20]; char buildingname[20]; struct Graph graph; graph.numBuildings = 0; graph.numEdges = 0; FILE* buildingFile = fopen("地点.txt", "r"); if (buildingFile == NULL) { printf("无法打开地点文件。\n"); return 1; } char line[100]; while (fgets(line, sizeof(line), buildingFile)) { char name[MAX_NAME_LENGTH]; char description[100]; sscanf(line, "%[^,],%[^\n]", name, description); addBuilding(&graph, graph.numBuildings + 1, name, description); } fclose(buildingFile); FILE* distanceFile = fopen("距离.txt", "r"); if (distanceFile == NULL) { printf("无法打开距离文件。\n"); return 1; } while (fgets(line, sizeof(line), distanceFile)) { char startName[MAX_NAME_LENGTH]; char endName[MAX_NAME_LENGTH]; int distance; sscanf(line, "%[^,],%[^,],%d", startName, endName, &distance); int start = findBuildingId(&graph, startName); int end = findBuildingId(&graph, endName); if (start != -1 && end != -1) { addEdge(&graph, start, end, distance); } } fclose(distanceFile); // 循环展示菜单,等待用户输入选项 while (1) { printf("1. 插入参赛队伍\n"); printf("2. 删除参赛队伍\n"); printf("3. 修改参赛队伍\n"); printf("4. 查找参赛队伍\n"); printf("5. 按参赛学校查询参赛队伍\n"); printf("6. 按赛事类别查询参赛队伍\n"); printf("7. 建筑物介绍\n"); printf("8. 导航查询最短距离\n"); printf("9. 决赛叫号系统\n"); printf("10. 退出\n"); printf("请选择操作:"); scanf("%d", &choice); switch (choice) { case 1: printf("请输入参赛队伍信息:\n"); Team newTeam; printf("参赛队编号:"); scanf("%s", newTeam.teamID); getchar(); // 消耗换行符 printf("参赛作品名称:"); fgets(newTeam.projectName, sizeof(newTeam.projectName), stdin); newTeam.projectName[strcspn(newTeam.projectName, "\n")] = '\0'; printf("参赛学校:"); fgets(newTeam.school, sizeof(newTeam.school), stdin); newTeam.school[strcspn(newTeam.school, "\n")] = '\0'; printf("赛事类别:"); fgets(newTeam.category, sizeof(newTeam.category), stdin); newTeam.category[strcspn(newTeam.category, "\n")] = '\0'; printf("参赛者:"); fgets(newTeam.participant, sizeof(newTeam.participant), stdin); newTeam.participant[strcspn(newTeam.participant, "\n")] = '\0'; printf("指导老师:"); fgets(newTeam.advisor, sizeof(newTeam.advisor), stdin); newTeam.advisor[strcspn(newTeam.advisor, "\n")] = '\0'; insertTeam(&root, newTeam); // 插入新的参赛队伍 updata(root); printf("参赛队伍插入成功!\n"); break; case 2: printf("请输入要删除的参赛队编号:"); scanf("%s", teamID); deleteTeam(&root, teamID); // 删除指定的参赛队伍 break; case 3: printf("请输入要修改的参赛队编号:"); scanf("%s", teamID); modifyTeam(root, teamID); // 修改指定的参赛队伍 break; case 4: printf("请输入要查找的参赛队编号:"); scanf("%s", teamID); int asl; // 用于记录查找操作中的平均查找长度 BSTNode* result = searchTeam(root, teamID, &asl); // 查找指定的参赛队伍 if (result != NULL) { printf("查找成功!\n"); printf("平均查找长度:%d\n", asl); printTeamInfo(result->team); } else { printf("查找失败!\n"); } break; case 5: printf("请输入要查询的参赛学校:"); scanf("%s", school); printTeamsBySchool(root, school); // 按参赛学校查询参赛队伍 break; case 6: printf("请输入要查询的赛事类别:"); scanf("%s", category); printTeamsByCategory(root, category); // 按赛事类别查询参赛队伍 break; case 7: printf("请输入想了解的建筑物:"); scanf("%s", buildingname); printBuildingInfo(&graph, buildingname); break; case 8: printf("请输入当前位置:"); scanf("%s", siteA); printf("请输入目的地:"); scanf("%s", siteB); navigate(&graph, siteA, siteB); // 查询最短距离 break; case 9: printf("叫号系统正在启动中:"); //将不同类型分组 sortByCategory(root,entranceA, "A"); entranceCount = 0; sortByCategory(root, entranceB, "B"); entranceCount = 0; sortByCategory(root, entranceC, "C"); entranceCount = 0; sortByCategory(root, entranceD, "D"); entranceCount = 0; sortByCategory(root, entranceE, "E"); entranceCount = 0; sortByCategory(root, entranceF, "F"); entranceCount = 0; sortByCategory(root, entranceG, "G"); entranceCount = 0; sortByCategory(root, entranceH, "H"); entranceCount = 0; sortByCategory(root, entranceI, "I"); entranceCount = 0; int selectNum=0; printf("抽取的个数:"); scanf("%d", &selectNum); for (size_t en = 0; en < selectNum; en++) { int randomNum = (rand() % 30) + 1;// 生成随机整数 printTeamInfoBattle(entranceA[randomNum], 1); printTeamInfoBattle(entranceB[randomNum], 2); printTeamInfoBattle(entranceC[randomNum], 3); printTeamInfoBattle(entranceD[randomNum], 4); printTeamInfoBattle(entranceE[randomNum], 5); printTeamInfoBattle(entranceF[randomNum], 6); printTeamInfoBattle(entranceG[randomNum], 7); printTeamInfoBattle(entranceH[randomNum], 8); printTeamInfoBattle(entranceI[randomNum], 9); } break; case 10: destroyBST(root); printf("程序已退出。\n"); return 0; break; default: printf("无效的选项!\n"); break; } printf("\n"); } } BSTNode* buildBSTFromFile(const char* filename) { FILE* file = fopen(filename, "r"); if (file == NULL) { printf("无法打开文件 %s\n", filename); return NULL; } BSTNode* root = NULL; char line[300]; while (fgets(line, sizeof(line), file) != NULL) { line[strcspn(line, "\n")] = '\0'; char* token = strtok(line, "\t#\t"); Team team; strcpy(team.teamID, token); token = strtok(NULL, "\t#\t"); strcpy(team.projectName, token); token = strtok(NULL, "\t#\t"); strcpy(team.school, token); token = strtok(NULL, "\t#\t"); strcpy(team.category, token); for (int i = 0; i < 30; i++) { if (strcmp(token, TypesAndEntrances[i][0]) == 0) { strcpy(team.entrance, TypesAndEntrances[i][1]); } } token = strtok(NULL, "\t#\t"); strcpy(team.participant, token); token = strtok(NULL, "\t#\t"); strcpy(team.advisor, token); insertTeam(&root, team); } fclose(file); return root; } void insertTeam(BSTNode** root, Team team) { BSTNode* newNode = (BSTNode*)malloc(sizeof(BSTNode)); newNode->team = team; newNode->left = NULL; newNode->right = NULL; if (*root == NULL) { *root = newNode; } else { BSTNode* current = *root; while (1) { int cmp = strcmp(team.teamID, current->team.teamID); if (cmp < 0) { if (current->left == NULL) { current->left = newNode;//在左节点插入 break; } current = current->left; } else { if (current->right == NULL) { current->right = newNode;//在右节点插入 break; } current = current->right; } } } } void deleteTeam(BSTNode** root, char* teamID) { if (*root == NULL) { printf("没有找到相关的参赛队伍!\n"); return; } BSTNode* parent = NULL; BSTNode* current = *root; int found = 0; // 在二叉排序树中查找要删除的参赛队伍 while (current != NULL) { int cmp = strcmp(teamID, current->team.teamID); if (cmp == 0) { found = 1; break; } parent = current; if (cmp < 0) { current = current->left; } else { current = current->right; } } if (!found) { printf("没有找到相关的参赛队伍!\n"); return; } // 根据情况删除参赛队伍 if (current->left == NULL && current->right == NULL) { // 如果要删除的节点没有子节点 if (parent == NULL) { *root = NULL; } else if (parent->left == current) { parent->left = NULL; } else { parent->right = NULL; } free(current); } // 如果要删除的节点只有一个子节点 else if (current->left == NULL || current->right == NULL) { BSTNode* child = (current->left != NULL) ? current->left : current->right; if (parent == NULL) { *root = child; } else if (parent->left == current) { parent->left = child; } else { parent->right = child; } free(current); } // 如果要删除的节点有两个子节点 else { BSTNode* successor = current->right; BSTNode* successorParent = current; while (successor->left != NULL) { successorParent = successor; successor = successor->left; } strcpy(current->team.teamID, successor->team.teamID); strcpy(current->team.projectName, successor->team.projectName); strcpy(current->team.school, successor->team.school); strcpy(current->team.category, successor->team.category); strcpy(current->team.participant, successor->team.participant); strcpy(current->team.advisor, successor->team.advisor); if (successorParent->left == successor) { successorParent->left = successor->right; } else { successorParent->right = successor->right; } free(successor); } updata(root); printf("参赛队伍删除成功!\n"); } void modifyTeam(BSTNode* root, char* teamID) { if (root == NULL) { printf("没有找到相关的参赛队伍!\n"); return; } BSTNode* current = root; int found = 0; // 在二叉排序树中查找要修改的参赛队伍 while (current != NULL) { int cmp = strcmp(teamID, current->team.teamID); if (cmp == 0) { found = 1; break; } if (cmp < 0) { current = current->left; } else { current = current->right; } } if (!found) { printf("没有找到相关的参赛队伍!\n"); return; } // 修改参赛队伍的信息 printf("请输入修改后的参赛队伍信息:\n"); printf("参赛队编号:"); scanf("%s", current->team.teamID); getchar(); // 消耗换行符 printf("参赛作品名称:"); fgets(current->team.projectName, sizeof(current->team.projectName), stdin); current->team.projectName[strcspn(current->team.projectName, "\n")] = '\0'; printf("参赛学校:"); fgets(current->team.school, sizeof(current->team.school), stdin); current->team.school[strcspn(current->team.school, "\n")] = '\0'; printf("赛事类别:"); fgets(current->team.category, sizeof(current->team.category), stdin); current->team.category[strcspn(current->team.category, "\n")] = '\0'; printf("参赛者:"); fgets(current->team.participant, sizeof(current->team.participant), stdin); current->team.participant[strcspn(current->team.participant, "\n")] = '\0'; printf("指导老师:"); fgets(current->team.advisor, sizeof(current->team.advisor), stdin); current->team.advisor[strcspn(current->team.advisor, "\n")] = '\0'; updata(root); printf("参赛队伍修改成功!\n"); } BSTNode* searchTeam(BSTNode* root, char* teamID, int* asl) { if (root == NULL) { *asl = 0; return NULL; } BSTNode* current = root; int count = 0; // 在二叉排序树中查找指定的参赛队伍 while (current != NULL) { count++; int cmp = strcmp(teamID, current->team.teamID); if (cmp == 0) { *asl = count; return current; } if (cmp < 0) { current = current->left; } else { current = current->right; } } *asl = count; return NULL; } void printTeamInfo(Team team) { printf("参赛队编号:%s\n", team.teamID); printf("参赛作品名称:%s\n", team.projectName); printf("参赛学校:%s\n", team.school); printf("赛事类别:%s\n", team.category); printf("参赛者:%s\n", team.participant); printf("指导老师:%s\n", team.advisor); } void printTeamInfoBattle(Team *team,int num) { if (team!=NULL) { printf("【决赛室%d】\n参赛队信息如下:\n", num); printf("队号:%s\n", team->teamID); printf("赛事类别:%s\n", team->entrance); printf("学校:%s\n", team->school); printf("项目名称:%s\n", team->projectName); printf("指导老师:%s\n", team->advisor); printf("参赛选手:%s\n", team->participant); printf("\n比赛进行中,请等待比赛结束……\n\n"); delay(500); } else { printf("【决赛室%d】\n", num); printf("该决赛室内已无比赛选手……\n\n"); delay(500); } } void printTeamsBySchool(BSTNode* root, char* school) { if (root == NULL) { //printf("没有找到相关的参赛队伍!\n"); return; } if (strcmp(root->team.school, school) == 0) { printTeamInfo(root->team); } printTeamsBySchool(root->left, school); printTeamsBySchool(root->right, school); } void printTeamsByCategory(BSTNode* root, char* category) { if (root == NULL) { //printf("没有找到相关的参赛队伍!\n"); return; } if (root->left != NULL) { printTeamsByCategory(root->left, category); } if (strcmp(root->team.category, category) == 0) { printTeamInfo(root->team); } printTeamsByCategory(root->right, category); } void destroyBST(BSTNode* root) { if (root != NULL) { destroyBST(root->left); destroyBST(root->right); free(root); } } void addBuilding(struct Graph* graph, int id, const char* name, const char* description) { struct Building building; building.id = id; strncpy(building.name, name, MAX_NAME_LENGTH - 1); building.name[MAX_NAME_LENGTH - 1] = '\0'; strncpy(building.description, description, 99); building.description[99] = '\0'; graph->buildings[graph->numBuildings++] = building; } void addEdge(struct Graph* graph, int start, int end, int distance) { struct Edge edge; edge.start = start; edge.end = end; edge.distance = distance; graph->edges[graph->numEdges++] = edge; } int findBuildingId(struct Graph* graph, const char* name) { for (int i = 0; i < graph->numBuildings; i++) { if (strcmp(graph->buildings[i].name, name) == 0) { return i; } } return -1; } // 查询建筑物介绍 void printBuildingInfo(struct Graph* graph, const char* name) { int buildingId = findBuildingId(graph, name); if (buildingId == -1) { printf("无法找到指定的建筑物。\n"); return; } printf("建筑物名称:%s\n", graph->buildings[buildingId].name); printf("建筑物介绍:%s\n", graph->buildings[buildingId].description); } // 查询两地最短距离 void navigate(struct Graph* graph, const char* startName, const char* endName) { int start = findBuildingId(graph, startName); int end = findBuildingId(graph, endName); if (start == -1 || end == -1) { printf("无法找到指定的建筑物。\n"); return; } int distances[MAX_BUILDINGS]; int previous[MAX_BUILDINGS]; int visited[MAX_BUILDINGS]; int numVisited = 0; for (int i = 0; i < graph->numBuildings; i++) { distances[i] = INT_MAX; previous[i] = -1; visited[i] = 0; } distances[start] = 0; while (numVisited < graph->numBuildings) { int minDistance = INT_MAX; int current = -1; for (int i = 0; i < graph->numBuildings; i++) { if (!visited[i] && distances[i] < minDistance) { minDistance = distances[i]; current = i; } } if (current == -1) { break; } visited[current] = 1; numVisited++; for (int i = 0; i < graph->numEdges; i++) { if (graph->edges[i].start == current) { int neighbor = graph->edges[i].end; int distance = graph->edges[i].distance; int totalDistance = distances[current] + distance; if (totalDistance < distances[neighbor]) { distances[neighbor] = totalDistance; previous[neighbor] = current; } } } } if (previous[end] == -1) { printf("无法找到从%s到%s的路径。\n", startName, endName); return; } printf("从%s到%s的最短路径为:\n", startName, endName); printf("%s", graph->buildings[start].name); int path[MAX_BUILDINGS]; int pathLength = 0; int current = end; while (current != start) { path[pathLength++] = current; current = previous[current]; } for (int i = pathLength - 1; i >= 0; i--) { printf(" -> %s", graph->buildings[path[i]].name); } printf("\n"); } // 根据类型进行决赛分组 void sortByCategory(BSTNode* root, Team* entrance[], char* type) { if (root == NULL) { return; } if (root->left != NULL) { sortByCategory(root->left,entrance, type); } if (strcmp(root->team.entrance, type) == 0) { entrance[entranceCount] = &root->team; entranceCount++; } sortByCategory(root->right,entrance, type); }