数据结构课程设计————计算机设计大赛

目录

【问题描述】

【设计要求】

【概要设计】

数据结构设计

参赛队伍信息的数据结构

结构体Team

添加队伍信息

修改队伍信息

删除队伍信息

导入参赛队伍信息

二叉树查找

【源代码】


【问题描述】

  本次课程设计要求协助中国大学生计算机设计大赛江苏省组委会,设计一款赛事管理系统,实现赛务相关的数据管理及信息服务,该系统能够为省级赛事管理解决以下问题:

(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;
}



  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JUST-showmaker

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值