目录
【问题描述】
本次课程设计要求协助中国大学生计算机设计大赛江苏省组委会,设计一款赛事管理系统,实现赛务相关的数据管理及信息服务,该系统能够为省级赛事管理解决以下问题:
(1)能够管理各参赛队的基本信息(包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项(参见大赛官网jsjds.blcu.edu.cn);包括增加、删除、修改参赛队伍的信息。
(2)从team.txt中读取参赛队伍的基本信息,实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。
(3)能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队),即,根据提示输入参赛学校名称(赛事类别),若查找成功,输出该学校参赛的(该赛事类别的)所有团队的基本信息,输出的参赛团队按赛事类别有序输出。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)
(4)为省赛现场设计一个决赛叫号系统。所有参赛队按赛事组织文件中的赛事类别分到9个决赛室,决赛室按顺序叫号,被叫号参赛队进场,比赛结束后,下一参赛队才能进赛场。请模拟决赛叫号系统,演示省赛现场各决赛室的参赛队进场情况。(模拟时,要能直观展示叫号顺序与进场秩序一致)
(5)赛事系统为参赛者提供赛地的校园导游程序,为参赛者提供各种路径导航的查询服务。以我校长山校区提供比赛场地为例,(请为参赛者提供不少于10个目标地的导航。可为参赛者提供校园地图中任意目标地(建筑物)相关信息的查询;提供任意两个目标地(建筑物)的导航查询,即查询任意两个目的地(建筑物)之间的一条最短路径。
【设计要求】
1)赛事数据要求存入文件(txt或excel)并能读入查询;
2)赛地目的地查询,需提供目的地(建筑物)名称、代号、简介、两地之间路径长度等信息;
3)输入数据形式和范围:赛事相关数据可从键盘输入,或自文件导入。
4)界面要求:交互设计要合理,每个功能可以设计菜单,用户根据提示,完成相关功能的要求。
【概要设计】
数据结构设计
参赛队伍信息的数据结构
结构体Team
结构体Team用于储存参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师相关信息。
struct Team{
string id; //编号
string OpusName;//作品名
string School;//学校
string EventCategory;//类别
string Player;//参赛者
string Teacher;//老师
};
添加队伍信息
函数addTeam,将输入的信息插入到新结点中。
void addTeam() {
Team s;
cout << "请输入参赛团队编号: ";
cin >> s.id;
cout << "请输入参赛团队作品名称: ";
cin >> s.OpusName;
cout << "请输入参赛团队学校: ";
cin >> s.School;
cout << "请输入参赛类别: ";
cin >> s.EventCategory;
cout << "请输入参赛队员: ";
cin >> s.Player;
cout << "请输入指导老师: ";
cin >> s.Teacher;
insert(s); //将输入的信息插入到新结点中
}
修改队伍信息
modifyTeam函数,输入要修改的队伍编号,重新输入该队伍信息。
void modifyTeam(string id) {
deleteNode(root,id); // 删除结点信息
Team s;
cout << "请输入参赛团队编号: ";
cin >> s.id;
cout << "请输入参赛团队作品名称: ";
cin >> s.OpusName;
cout << "请输入参赛团队学校: ";
cin >> s.School;
cout << "请输入参赛类别: ";
cin >> s.EventCategory;
cout << "请输入参赛队员: ";
cin >> s.Player;
cout << "请输入指导老师: ";
cin >> s.Teacher;
insert(s); // 插入到二叉树中
}
删除队伍信息
deleteNode函数,输入要删除的队伍,在二叉树中搜索并删除。
Node* deleteNode(Node* root, string id) {
if (root == NULL) return root;
if (id < root->data.id) { // 如果要刪除的编号小于根结点的编号,在右子树返回删除
root->left = deleteNode(root->left, id);
}
else if (id > root->data.id) { // 如果要刪除的编号大于根结点的编号,在左子树返回删除
root->right = deleteNode(root->right, id);
}
else { //找到该结点
if (root->left == NULL && root->right == NULL) { // 该结点没有子结点,直接删除返回空
delete root;
return NULL;
}
else if (root->left == NULL) { // 该结点只有右子结点,替换成右子结点
Node* temp = root->right;
delete root;
return temp;
}
else if (root->right == NULL) { // 该结点只有左子结点,替换成左子结点
Node* temp = root->left;
delete root;
return temp;
}
else { // 若有两个结点,替换为左子树中最大值或右子树中最小值
Node* temp = minValueNode(root->right); // 找到右子树的最小值
root->data = temp->data; // 最小值替换
root->right = deleteNode(root->right, temp->data.id); // 删除
}
}
return root; // 返回新的根结点
}
导入参赛队伍信息
readTeam函数,每一行为一个队伍的信息。
isEndOfFile函数,查看下一字符是否为文件结束符。
//读取信息,#为分隔
Team readTeam(istream& in) {
Team s;
getline(in, s.id, '#');
getline(in, s.OpusName, '#');
getline(in, s.School, '#');
getline(in, s.EventCategory, '#');
getline(in, s.Player, '#');
getline(in, s.Teacher);
return s;
}
bool isEndOfFile(ifstream& file) {
char c = file.peek(); // 查看下一个字符
if (c == EOF) { // 若下一个字符为文件结束符,返回true
return true;
}
return false;
}
//以下为调用函数中的文件读取内容
ifstream file;
file.open("team.txt");
while (!isEndOfFile(file)) { // 循环到文件结束
Team s = readTeam(file); // 读取, 每一行为一个队伍
tree.insert(s); // 将队伍信息插入二叉树
}
file.close();
二叉树查找
创建二叉树的类,
Team *root = NULL;
int searchCount = 0;
int searchTotal = 0;
结点结构体,包括信息,左右字子树
struct Node {
Team data;
Node* left;
Node* right;
};
createNode函数,创建新结点
Node* createNode(Team data) {
Node* newNode = new Node();
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
insertNode函数,将新结点插入到二叉树中。(平衡二叉树,方便按编号大有序输出队伍信息)
insert函数,调用insertNode函数,来插入队伍信息,读取文件和添加修改队伍信息也会用到。
Node* insertNode(Node* node, Team data) {
if (node == NULL) { // 若结点为空,将新结点作为根结点
size++; //结点数加1
return createNode(data);
}
if (data.id < node->data.id) { // 新结点学号小于当前结点,插入到左子树
node->left = insertNode(node->left, data);
}
else if (data.id > node->data.id) { // 新结点学号小于当前结点,插入到左子树
node->right = insertNode(node->right, data);
}
return node;
}
printTeam函数,输出队伍信息。
void printTeam(Team s) {
cout << "参赛团队编号: " << s.id << endl;
cout << "参赛作品名称: " << s.OpusName << endl;
cout << "参赛团队学校: " << s.School << endl;
cout << "参赛类型: " << s.EventCategory << endl;
cout << "参赛队员: " << s.Player << endl;
cout << "指导老师: " << s.Teacher << endl;
}
searchNode函数,在二叉树中所有参数中的id,并记录查找次数。
search函数,调用searchNode函数来实现对ID的查找。
//在二叉树中搜索该学号
Node* searchNode(Node* node, string id, int& count) {
if (node == NULL) { // 若结点为空或没有找到,返回NULL
return NULL;
}
count++; // 查找次数加一
if (id == node->data.id) { // 如果找到匹配的结点,返回该结点指针
return node;
}
if (id < node->data.id) { // 若查找学号小于该结点学号,在左子树中查找
return searchNode(node->left, id, count);
}
else { // 若查找学号大于该结点学号,在右子树中查找
return searchNode(node->right, id, count);
}
}
Node* search(string id) {
int count = 0; // 记录查找次数
Node* node = searchNode(root, id, count);
totalSearch += count; // 查找次数累加
return node; // 返回查找结点
}
getASL函数,计算平均查找长度。
// 平均查找长度ASL
double getASL() {
if (size == 0) { // 若树为空,返回0
return 0;
}
return (double)totalSearch / size;
}
printSameSchool函数,找到该学校所有参赛队伍的信息。
void printSameSchool(Node* root,string School) {
if (root == NULL) return; // 结点为空返回
printSameSchool(root->left,School); // 遍历左子树
if (root->data.School == School) { // 当前结点和输入学校相同,输出该结点的信息
printTeam(root->data);
}
printSameSchool(root->right,School); // 遍历右子树
}
base函数,前三题调用函数,用来实现要求功能。
BST tree;
//导入参赛团队信息
ifstream file;
file.open("team.txt");
while (!isEndOfFile(file)) { // 循环到文件结束
Team s = readTeam(file); // 读取, 每一行为一个队伍
tree.insert(s); // 将队伍信息插入二叉树
}
file.close();
int option1;
string searchid,reviseid,deleteid,SameSchool;
cout << "——————1.添加参赛队伍信息——————" << endl;
cout << "——————2.修改参赛队伍信息——————" << endl;
cout << "——————3.删除参赛队伍信息——————" << endl;
cout << "——————4.查找参赛队伍信息——————" << endl;
cout << "——————5.查找学校参赛信息——————" << endl;
cout << endl;
cout << "请选择你的操作:";
cin >> option1;
switch (option1)
{
case 1:
tree.addTeam();
break;
case 2:
cout << "请输入你要修改的队伍编号:";
cin >> reviseid;
tree.modifyTeam(reviseid);
break;
case 3:
cout << "请输入你要删除的队伍编号:";
cin >> deleteid;
tree.deleteNode(tree.root,deleteid);
break;
case 4:
while (true) { // 循环执行操作
cout << "请输入要查找的学号,或者输入0退出程序: ";
cin >> searchid;
if (searchid == "0") break; // 输入0跳出循环
Node* node = tree.search(searchid); // 在二叉树中搜索该编号对应的节点
if (node == NULL) { // 没有找到
cout << "查找失败" << endl;
}
else { // 输出队伍信息以及平均查找长度ASL
cout << "查找成功" << endl;
printTeam(node->data);
cout << "平均查找长度ASL: " << tree.getASL() << endl;
}
cout << endl;
}
cout << "退出查找" << endl;
case 5:
cout << "请输入你要查找的学校名字:";
cin >> SameSchool;
tree.printSameSchool(tree.root,SameSchool);
break;
default:
break;
}
}
【源代码】
#include<iostream>
#include <limits.h>
#include <fstream>
#include <string>
#include <queue>
using namespace std;
struct Team {
string id; //编号
string OpusName;//作品名
string School;//学校
string EventCategory;//类别
string Player;//参赛者
string Teacher;//老师
};
struct Node {
Team data;
Node* left;
Node* right;
};
class BST {
private:
// 创建新结点
Node* createNode(Team data) {
Node* newNode = new Node();
newNode->data = data;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
// 将新结点插入二叉树中
Node* insertNode(Node* node, Team data) {
if (node == NULL) { // 若结点为空,将新结点作为根结点
size++; //结点数加1
return createNode(data);
}
if (data.id < node->data.id) { // 新结点编号小于当前结点,插入到左子树
node->left = insertNode(node->left, data);
}
else if (data.id > node->data.id) { // 新结点编号小于当前结点,插入到左子树
node->right = insertNode(node->right, data);
}
return node;
}
//在二叉树中搜索该编号
Node* searchNode(Node* node, string id, int& count) {
if (node == NULL) { // 若结点为空或没有找到,返回NULL
return NULL;
}
count++; // 查找次数加一
if (id == node->data.id) { // 如果找到匹配的结点,返回该结点指针
return node;
}
if (id < node->data.id) { // 若查找编号小于该结点编号,在左子树中查找
return searchNode(node->left, id, count);
}
else { // 若查找编号大于该结点编号,在右子树中查找
return searchNode(node->right, id, count);
}
}
// 中序遍历二叉树,输出所有队伍信息
void inorder(Node* node) {
if (node == NULL) { // 如果结点是空的,則返回
return;
}
inorder(node->left); // 遍历左子树
printTeam(node->data); // 输出当前结点的队伍信息
cout << endl;
inorder(node->right); // 遍历右子树
}
public:
Node* root; // 根结点指针
int size; //结点数
int totalSearch; // 查找次数
BST() { // 构造函數,初始化根结点、结点数量和查找次数
root = NULL;
size = 0;
totalSearch = 0;
}
~BST() { // 析构函数,释放所有动态分配的空间
deleteTree(root); // 刪除二叉树中的所有结点
}
//最小值结点
Node* minValueNode(Node* node) {
if (node == NULL) return NULL; // 如果结点是空的,返回空
while (node->left != NULL) { // 若有左子树,继续寻找
node = node->left;
}
return node; // 返回最左边的结点
}
void deleteTree(Node* node) {
if (node == NULL) {
return;
}
deleteTree(node->left); // 刪除左子树
deleteTree(node->right); // 刪除右子树
delete node; // 刪除当前结点
}
//删除参赛队伍信息
Node* deleteNode(Node* root, string id) {
if (root == NULL) return root;
if (id < root->data.id) { // 如果要刪除的编号小于根结点的编号,在右子树返回删除
root->left = deleteNode(root->left, id);
}
else if (id > root->data.id) { // 如果要刪除的编号大于根结点的编号,在左子树返回删除
root->right = deleteNode(root->right, id);
}
else { //找到该结点
if (root->left == NULL && root->right == NULL) { // 该结点没有子结点,直接删除返回空
delete root;
return NULL;
}
else if (root->left == NULL) { // 该结点只有右子结点,替换成右子结点
Node* temp = root->right;
delete root;
return temp;
}
else if (root->right == NULL) { // 该结点只有左子结点,替换成左子结点
Node* temp = root->left;
delete root;
return temp;
}
else { // 若有两个结点,替换为左子树中最大值或右子树中最小值
Node* temp = minValueNode(root->right); // 找到右子树的最小值
root->data = temp->data; // 最小值替换
root->right = deleteNode(root->right, temp->data.id); // 删除
}
}
return root; // 返回新的根结点
}
// 插入队伍信息
void insert(Team data) {
root = insertNode(root, data);
}
// 查找该编号
Node* search(string id) {
int count = 0; // 记录查找次数
Node* node = searchNode(root, id, count);
totalSearch += count; // 查找次数累加
return node; // 返回查找结点
}
// 平均查找长度ASL
double getASL() {
if (size == 0) { // 若树为空,返回0
return 0;
}
return (double)totalSearch / size;
}
// 中序遍历二叉树
void inorder() {
inorder(root); //
}
//添加队伍信息
void addTeam() {
Team s;
cout << "请输入参赛团队编号: ";
cin >> s.id;
cout << "请输入参赛团队作品名称: ";
cin >> s.OpusName;
cout << "请输入参赛团队学校: ";
cin >> s.School;
cout << "请输入参赛类别: ";
cin >> s.EventCategory;
cout << "请输入参赛队员: ";
cin >> s.Player;
cout << "请输入指导老师: ";
cin >> s.Teacher;
insert(s); //将输入的信息插入到新结点中
}
//修改队伍信息
void modifyTeam(string id) {
deleteNode(root, id); // 删除结点信息
Team s;
cout << "请输入参赛团队编号: ";
cin >> s.id;
cout << "请输入参赛团队作品名称: ";
cin >> s.OpusName;
cout << "请输入参赛团队学校: ";
cin >> s.School;
cout << "请输入参赛类别: ";
cin >> s.EventCategory;
cout << "请输入参赛队员: ";
cin >> s.Player;
cout << "请输入指导老师: ";
cin >> s.Teacher;
insert(s); // 插入到二叉树中
}
//找到某学校的所有参赛队伍的信息
void printSameSchool(Node* root, string School) {
if (root == NULL) return; // 结点为空返回
printSameSchool(root->left, School); // 遍历左子树
if (root->data.School == School) { // 当前结点和输入学校相同,输出该结点的信息
printTeam(root->data);
cout << "——————————————" << endl;
}
printSameSchool(root->right, School); // 遍历右子树
}
void printTeam(Team s) {
cout << "参赛团队编号: " << s.id << endl;
cout << "参赛作品名称: " << s.OpusName << endl;
cout << "参赛团队学校: " << s.School << endl;
cout << "参赛类型: " << s.EventCategory << endl;
cout << "参赛队员: " << s.Player << endl;
cout << "指导老师: " << s.Teacher << endl;
}
//将二叉树中的队伍分配到三个教室中,使用队列存储每个教室的队伍
void assignroom(Node* root, queue<Node*>& room1, queue<Node*>& room2, queue<Node*>& room3, queue<Node*>& room4, queue<Node*>& room5, queue<Node*>& room6, queue<Node*>& room7, queue<Node*>& room8, queue<Node*>& room9) {
if (root == NULL) return; //如果节点为空,直接返回
assignroom(root->left, room1, room2, room3, room4, room5, room6, room7, room8, room9); //分配左子树中的队伍
if (root->data.EventCategory == "大数据实践") {
room1.push(root);
}
else if (root->data.EventCategory == "信息图形设计") {
room2.push(root);
}
else if (root->data.EventCategory == "数据可视化") {
room3.push(root);
}
else if (root->data.EventCategory == "算法设计与应用") {
room4.push(root);
}
else if (root->data.EventCategory == "移动应用开发") {
room5.push(root);
}
else if (root->data.EventCategory == "医药卫生") {
room6.push(root);
}
else if (root->data.EventCategory == "数字生活") {
room7.push(root);
}
else if (root->data.EventCategory == "城市管理") {
room8.push(root);
}
else if (root->data.EventCategory == "行业应用") {
room9.push(root);
}
assignroom(root->right, room1, room2, room3, room4, room5, room6, room7, room8, room9); //分配右子树中的学生
}
//模拟叫号系统,按照教室顺序叫号,被叫号的队伍进入比赛,比赛结束后下一个队伍才能进入
void simulateCall(queue<Node*>& room1, queue<Node*>& room2, queue<Node*>& room3, queue<Node*>& room4, queue<Node*>& room5, queue<Node*>& room6, queue<Node*>& room7, queue<Node*>& room8, queue<Node*>& room9) {
cout << "--------------------------" << endl; //打印分隔符
while (!room1.empty()) { //如果教室不为空,叫号并出队
Node* s = room1.front();
cout << "大数据实践叫号:" << s->data.id << " " << s->data.OpusName << endl;
cout << s->data.OpusName << "进入大数据实践教室比赛" << endl;
cout << s->data.OpusName << "比赛结束" << endl;
room1.pop();
}
cout << "--------------------------" << endl; //打印分隔符
while (!room2.empty()) {
Node* s = room2.front();
cout << "信息图形设计叫号:" << s->data.id << " " << s->data.OpusName << endl;
cout << s->data.OpusName << "进入信息图形设计比赛" << endl;
cout << s->data.OpusName << "比赛结束" << endl;
room2.pop();
}
cout << "--------------------------" << endl; //打印分隔符
while (!room3.empty()) {
Node* s = room3.front();
cout << "数据可视化叫号:" << s->data.id << " " << s->data.OpusName << endl;
cout << s->data.OpusName << "进入数据可视化比赛" << endl;
cout << s->data.OpusName << "比赛结束" << endl;
room3.pop();
}
cout << "--------------------------" << endl; //打印分隔符
while (!room4.empty()) {
Node* s = room4.front();
cout << "算法设计与应用叫号:" << s->data.id << " " << s->data.OpusName << endl;
cout << s->data.OpusName << "进入算法设计与应用比赛" << endl;
cout << s->data.OpusName << "比赛结束" << endl;
room4.pop();
}
cout << "--------------------------" << endl; //打印分隔符
while (!room5.empty()) {
Node* s = room5.front();
cout << "移动应用开发叫号:" << s->data.id << " " << s->data.OpusName << endl;
cout << s->data.OpusName << "进入移动应用开发比赛" << endl;
cout << s->data.OpusName << "比赛结束" << endl;
room5.pop();
}
cout << "--------------------------" << endl; //打印分隔符
while (!room6.empty()) {
Node* s = room6.front();
cout << "医药卫生叫号:" << s->data.id << " " << s->data.OpusName << endl;
cout << s->data.OpusName << "进入医药卫生比赛" << endl;
cout << s->data.OpusName << "比赛结束" << endl;
room6.pop();
}
cout << "--------------------------" << endl; //打印分隔符
while (!room7.empty()) {
Node* s = room7.front();
cout << "数字生活叫号:" << s->data.id << " " << s->data.OpusName << endl;
cout << s->data.OpusName << "进入数字生活比赛" << endl;
cout << s->data.OpusName << "比赛结束" << endl;
room7.pop();
}
cout << "--------------------------" << endl; //打印分隔符
while (!room8.empty()) {
Node* s = room8.front();
cout << "城市管理叫号:" << s->data.id << " " << s->data.OpusName << endl;
cout << s->data.OpusName << "进入城市管理比赛" << endl;
cout << s->data.OpusName << "比赛结束" << endl;
room8.pop();
}
cout << "--------------------------" << endl; //打印分隔符
while (!room9.empty()) {
Node* s = room9.front();
cout << "行业应用叫号:" << s->data.id << " " << s->data.OpusName << endl;
cout << s->data.OpusName << "进入行业应用比赛" << endl;
cout << s->data.OpusName << "比赛结束" << endl;
room9.pop();
}
}
};
void printTeam(Team s) {
cout << "参赛团队编号: " << s.id << endl;
cout << "参赛作品名称: " << s.OpusName << endl;
cout << "参赛团队学校: " << s.School << endl;
cout << "参赛类型: " << s.EventCategory << endl;
cout << "参赛队员: " << s.Player << endl;
cout << "指导老师: " << s.Teacher << endl;
}
//读取信息,#为分隔
Team readTeam(istream& in) {
Team s;
getline(in, s.id, '#');
getline(in, s.OpusName, '#');
getline(in, s.School, '#');
getline(in, s.EventCategory, '#');
getline(in, s.Player, '#');
getline(in, s.Teacher);
return s;
}
bool isEndOfFile(ifstream& file) {
char c = file.peek(); // 查看下一个字符
if (c == EOF) { // 若下一个字符为文件结束符,返回true
return true;
}
return false;
}
// 定义一个结构体,储存目的地信息
struct Destination {
string name; // 目的地名称
string code; // 目的地代号
string intro; // 目的地简介
};
// 定义一个常量,表示无穷大
const int INF = INT_MAX;
// 定义一个常量,表示图形中节点的个数
const int V = 10;
// 定义一个函数,找到未被访问过的距离最小的节点
int minDistance(int dist[], bool visited[]) {
int min = INF, min_index;
for (int v = 0; v < V; v++) {
if (visited[v] == false && dist[v] <= min) {
min = dist[v], min_index = v;
}
}
return min_index;
}
// 定义一个函数,打印最短路径和长度
void printPath(int parent[], int j, Destination destinations[]) {
if (parent[j] == -1) {
return;
}
printPath(parent, parent[j], destinations);
cout << " -> " << destinations[j].code;
}
void printSolution(int dist[], int n, int parent[], int src, int dest, Destination destinations[]) {
cout << "Vertex\t\tDistance\tPath";
cout << "\n" << destinations[src].code << " -> " << destinations[dest].code << "\t\t" << dist[dest] << "\t\t" << destinations[src].code;
printPath(parent, dest, destinations);
}
// 定义一个函数,实现Dijkstra算法
void dijkstra(int graph[V][V], int src, int dest, Destination destinations[]) {
int dist[V]; // 储存源点到各个节点的距离
bool visited[V]; // 储存各个节点是否被访问过
int parent[V]; // 储存最短路径中各个节点的父节点
// 初始化各个数组
for (int i = 0; i < V; i++) {
dist[i] = INF;
visited[i] = false;
parent[i] = -1;
}
// 源点到自己的距离为0
dist[src] = 0;
// 遍历所有节点
for (int count = 0; count < V - 1; count++) {
// 找到未被访问过的距离最小的节点
int u = minDistance(dist, visited);
// 标记该节点为已访问过
visited[u] = true;
// 更新该节点相邻节点的距离和父节点
for (int v = 0; v < V; v++) {
if (!visited[v] && graph[u][v] && dist[u] != INF && dist[u] + graph[u][v] < dist[v]) {
dist[v] = dist[u] + graph[u][v];
parent[v] = u;
}
}
}
// 打印最短路径和长度
printSolution(dist, V, parent, src, dest, destinations);
}
int guide() {
// 创建一个二维数组,表示图形中各个节点之间的距离(权值)
int graph[V][V] = {
{0, 144, 0, 0, 0, 0, 0, 148, 0},
{144, 0, 148, 0, 0, 0, 0, 151, 0},
{0, 148, 0, 147, 0, 144, 0, 0, 142},
{0, 0, 147, 0, 149, 154, 0, 0, 0},
{0, 0, 0, 149, 0, 150, 0, 0, 0},
{0, 0, 144, 154, 150, 0, 142, 0, 0},
{0, 0, 0, 0, 0, 142, 0, 141, 146},
{148, 151, 0, 0, 0, 0, 141, 0, 147},
{0, 0, 142, 0, 0, 0, 146,147, 0}
};
// 创建一个结构体数组,储存各个目的地的信息
Destination destinations[V] = { {"1号组团", "A", "学生宿舍"},
{"3号组团", "B", "学生宿舍"},
{"西苑食堂", "C", "食堂"},
{"笃学楼", "D", "教学楼"},
{"文理大楼", "E", "学校主楼"},
{"计算机学院", "F", "计算机学院办公楼"},
{"东苑食堂", "G", "食堂"},
{"体育馆", "H", "大学生活动中心"},
{"8号组团", "I", "学生宿舍"},
{"图书馆", "J", "图书馆和自习室"}
};
for (int i = 0; i < V; i++) {
cout << destinations[i].name << "(" << destinations[i].code << "):" << destinations[i].intro << endl;
}
// 创建一个字符串变量,储存用户输入的两个目的地代号
char a, b;
// 提示用户输入两个目的地代号
cout << "请输入目的地代号:";
// 获取用户输入
cin >> a >> b;
// 将用户输入的两个目的地代号转换为对应的节点编号
int src = a - 'A';
int dest = b - 'A';
// 检查用户输入的两个目的地是否有效
if (src < 0 || src >= V || dest < 0 || dest >= V) {
cout << "输入错误,请重新输入!" << endl;
return -1;
}
// 检查用户输入的两个目的地是否相同
if (src == dest) {
cout << "输入错误,请重新输入!" << endl;
return -1;
}
// 输出用户查询的两个目的地的信息
cout << "\n地点信息:" << endl;
cout << destinations[src].name << "(" << destinations[src].code << "):" << destinations[src].intro << endl;
cout << destinations[dest].name << "(" << destinations[dest].code << "):" << destinations[dest].intro << endl;
// 调用Dijkstra算法,输出最短路径和长度
cout << "\n最短路径和长度是:" << endl;
dijkstra(graph, src, dest, destinations);
return 0;
}
void base() {
BST tree;
//导入参赛团队信息
ifstream file;
file.open("team.txt");
while (!isEndOfFile(file)) { // 循环到文件结束
Team s = readTeam(file); // 读取, 每一行为一个队伍
tree.insert(s); // 将队伍信息插入二叉树
}
file.close();
int option1;
string searchid, reviseid, deleteid, SameSchool;
cout << "——————1.添加参赛队伍信息——————" << endl;
cout << "——————2.修改参赛队伍信息——————" << endl;
cout << "——————3.删除参赛队伍信息——————" << endl;
cout << "——————4.查找参赛队伍信息——————" << endl;
cout << "——————5.查找学校参赛信息——————" << endl;
cout << "——————6.叫号系统——————————" << endl;
cout << "——————7.校园导航系统————————" << endl;
cout << endl;
cout << "请选择你的操作:";
cin >> option1;
switch (option1)
{
case 1:
tree.addTeam();
cout << "添加成功!" << endl;
break;
case 2:
cout << "请输入你要修改的队伍编号:";
cin >> reviseid;
tree.modifyTeam(reviseid);
cout << "修改成功!" << endl;
break;
case 3:
cout << "请输入你要删除的队伍编号:";
cin >> deleteid;
tree.deleteNode(tree.root, deleteid);
cout << "删除成功!" << endl;
break;
case 4:
while (true) { // 循环执行操作
cout << "请输入要查找的学号,或者输入0退出程序: ";
cin >> searchid;
if (searchid == "0") break; // 输入0跳出循环
Node* node = tree.search(searchid); // 在二叉树中搜索该编号对应的节点
if (node == NULL) { // 没有找到
cout << "查找失败" << endl;
}
else { // 输出队伍信息以及平均查找长度ASL
cout << "查找成功" << endl;
printTeam(node->data);
cout << "平均查找长度ASL: " << tree.getASL() << endl;
}
cout << endl;
}
cout << "退出查找" << endl;
break;
case 5:
cout << "请输入你要查找的学校名字:";
cin >> SameSchool;
tree.printSameSchool(tree.root, SameSchool);
break;
case 6:
{
queue<Node*>room1; queue<Node*>room2; queue<Node*>room3; queue<Node*>room4; queue<Node*>room5; queue<Node*>room6; queue<Node*>room7; queue<Node*>room8; queue<Node*>room9;
tree.assignroom(tree.root, room1, room2, room3, room4, room5, room6, room7, room8, room9);
cout << "————开始模拟叫号系统————" << endl;
tree.simulateCall(room1, room2, room3, room4, room5, room6, room7, room8, room9);
break;
}
case 7:
guide();
break;
default:
break;
}
}
int main() {
base();
return 0;
}