数据结构课程设计预习报告(文件管理,数据查询,校园导航,叫号系统等)

文章描述了一个针对中国大学生计算机设计大赛的赛事管理系统的设计要求,包括参赛队伍信息管理、二叉排序树查找、按学校或类别查询、决赛叫号系统模拟和校园导航功能。通过C++实现数据结构和算法,以优化信息处理和提升用户体验。
摘要由CSDN通过智能技术生成

一,问题描述

中国大学生计算机设计大赛是我国高校面向本科生的计算机应用设计大赛,大赛旨在激发学生学习计算机知识和技能的兴趣与潜能,提高学生运用信息技术解决实际问题的综合能力。通过大赛这种计算机教学实践形式,可展示师生的教与学成果,最终以赛促学,以赛促教,以赛促创。该赛事在历届学生中影响力较大,参与者众多,请结合2021届省赛参赛的数据,借助数据结构课程所学的相关知识,通过对数据的处理和分析,熟悉数据结构设计及数据处理在信息管理系统中应用的重要性。赛事相关数据存储在文本文件和excel文件中,相应的文件信息说明如表1所示。其中,各个文件中不同的数据项之间均使用#分隔。

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

(1)能够管理各参赛队的基本信息(包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项(参见大赛官网jsjds.blcu.edu.cn);包括增加、删除、修改参赛队伍的信息。

(2)从team.txt中读取参赛队伍的基本信息,实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。

(3)能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队),即,根据提示输入参赛学校名称(赛事类别),若查找成功,输出该学校参赛的(该赛事类别的)所有团队的基本信息,输出的参赛团队按赛事类别有序输出。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)

(4)为省赛现场设计一个决赛叫号系统。所有参赛队按赛事组织文件中的赛事类别分到9个决赛室,决赛室按顺序叫号,被叫号参赛队进场,比赛结束后,下一参赛队才能进赛场。请模拟决赛叫号系统,演示省赛现场各决赛室的参赛队进场情况。(模拟时,要能直观展示叫号顺序与进场秩序一致)

(5)赛事系统为参赛者提供赛地的校园导游程序,为参赛者提供各种路径导航的查询服务。以我校长山校区提供比赛场地为例,(请为参赛者提供不少于10个目标地的导航。可为参赛者提供校园地图中任意目标地(建筑物)相关信息的查询;提供任意两个目标地(建筑物)的导航查询,即查询任意两个目的地(建筑物)之间的一条最短路径。

 

二,问题分析

  • 问题一


    这是一个数据管理问题,包含了文件读取和修改的操作。我们可以用C++标准模板库中的vector容器实现存储,先将文件定义为一个流对象,在定义一个team结构体(包含string number;string name;string school;string kind;string participant;string teacher这几个属性) 

    struct Team
    {
        string number;
        string name;
        string school;
        string kind;
        string participant;
        string teacher;
    };

    再使用getline函数按行以“#”为分隔按行读取数据,存储到结构体中,再使用vector中的.push_back()函数将每一个结构体压入容器中。这样我们就可以得到按照不同属性存储的不同数据,方便后期管理。1)关于增加数据方面:创建一个新的team,并按照用户的输入对其进行初始化,初始化完成后将其压入容器中,再读取容器中的数据,并按“#”为间隔写入文件。2)关于数据修改方面:先创建一个字符串匹配函数bool is match(string father,string son),若父串中存在子串则return ture,子串不匹配则return false;(这个函数之后会多次使用)按照用户的输入的编号来匹配,若成功,则找到这一项vector<team>data[i],按照用户的输入进行数据修改,之后再写入文件。3)关于数据删除方面:使用is match字符串匹配函数,按照用户的输入的编号来匹配,若成功,调用erase函数进行对vector容器中的数据进行删除。之后再写入文件。

  • vector的使用可以参考这个

  • 问题二


    先创建一个二叉排序树结构体struct TreeNode,包含左右指针,数据项为team结构体。

  • //构建二叉排序树
    struct TreeNode
    {
        Team val;
        struct TreeNode* left;//指针域 左指针
        struct TreeNode* right;//指针域 右指针
        TreeNode(Team s):val(s), left(nullptr), right(nullptr) {}
    };
    
    TreeNode* root = nullptr;

    之后再写一个插入函数void insert(TreeNode*& root, Team s) ,将每一个结构体按照其编号属性按照二叉排序树的规则插入二叉树中。再写一个bool search(TreeNode* root, int num)函数,使用递归的方法查找是否存在要查找的数据,存在就返回true,不存在就返回false。函数int countNodes(TreeNode* root)// 计算二叉排序树的节点个数,函数int getDepth(TreeNode* root, TreeNode* node, int depth),计算二叉树深度,函数float ASL(TreeNode* root)//计算二叉排序树的ASL(即所有节点的深度之和除以节点个数)。按照用户输入进行查找,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。

  • 问题三


    先写一个比较函数,对两个字符串的首字符进行比较,再调用sort(same.begin(), same.end(), compareBykind)函数进行比较//快速排序法,时间复杂度为n*log2(n),执行效率较高。

    bool compareBykind(const Team& p1, const Team& p2)//字典序比较 
    {
        return (Remove_Spaces(p1.kind)) < (Remove_Spaces(p2.kind));
    }
    
    
    void sort_kind(vector<Team>& same)//快速排序法,时间复杂度为n*log2(n),执行效率较高
    {
        sort(same.begin(), same.end(), compareBykind);
    }

    void sort(vector<Team>& data)//按学校查询并分类:新建一个vector<team>same容器,调用字符串匹配函数,遍历已经储存了数据的vector<team>data[i].school,当和用户输入的string school匹配时,将此data[i]压入same,最后,调用sort对same内的数据进行排序后输出。

  • 问题四


    叫号系统:先新建9个vector容器,代表9个比赛房间。

    vector<Team> kind1;//大数据运用:大数据实践
        vector<Team> kind2;//信息可视化设计:信息图形设计,动态信息影像,交互信息设计,数据可视化
        vector<Team> kind3;//人工智能应用:人工智能实践赛,
        vector<Team> kind4;//软件应用与开发:Web应用与开发,管理信息系统,算法设计与应用,移动应用开发
        vector<Team> kind5;//物联网应用:医药卫生,数字生活,运动健身,城市管理,行业应用
        vector<Team> kind6;//数媒动漫与短片:动画,纪录片,数字短片,微电影,新媒体漫画
        vector<Team> kind7;//数媒静态设计:产品设计,环境设计,平面设计
        vector<Team> kind8;//数媒游戏与交互设计:交互媒体设计,游戏设计,虚拟现实
        vector<Team> kind9;//微课与教学辅助:汉语言文学,计算机基础与应用类课程微课,虚拟实验平台,中、小学数学或自然科学课程

    在调用字符串匹配函数is match()遍历vector<team>same,当字符串匹配将其压入相应的房间。当数据已经完全分类完之后,按照用户的选择进行对不同的房间进行比赛输出。使用this_thread::sleep_for(chrono::milliseconds(500))实现每次间隔0.5s输出,实现模拟目标。

  • 问题五


    校园导航系统:先创建一个结构体Attractions储存景点信息

    struct Attractions
    {
        int number;//景点编号
        string name;//景点名称
        string introduction;//景点介绍
        int distance;//Dijkstra算法中景点的权值
        int path; //记录当前顶点的前一个顶点编号
    };
    

    再创建一个无向图,保存地图信息

    struct Graph
    {
        Attractions vexs[11];
        int v,e;        // 图的顶点数,边数
        int** adj_matrix;  // 邻接矩阵
    };

    再对其添加边,以及每条边的长度,当两点之间没有边时,将长度初始化为10000。再使用Dijkstra算法求两个点之间的最短路径。

  • 初始化边

    void add_edge(Graph &G, int i, int j, int n)
    {
        G.adj_matrix[i][j] = n;
        G.adj_matrix[j][i] = n;
    }

  • Dijkstra算法:先创建一个空集合int S[10] = {},用于保存接下来遍历过的点,先添加源点n,就将s[n]=1。遍历每一个点,再对每个点的path进行初始化:若源点n和点i之间有路,则i.path=n;否则i.path=-1,表示无路。函数int findmindist(Graph G,int*s),寻找S集合中最小的distance值的点,并返回编号。并开始循环,依照distance值更新每个点的前驱节点。

    for (int i = 1; i <=G.v; i++)
                {
                    if ((S[i-1] == 0) && (G.vexs[i].distance > G.vexs[min].distance + G.adj_matrix[min][i]))
                    {
                        G.vexs[i].distance = G.vexs[min].distance + G.adj_matrix[min][i];
                        G.vexs[i].path = min;
                    }  
                }

    每次都选取S集合中最小distance值的节点作为下一次循环的起点,直到遍历完所有点。         最后,按照用户输入,使用int getnum(string str, Graph G)函数将用户输入的字符串地点转换为地点编号,调用函数void search_path(Graph &G,int n)//Dijkstra初始化,之后找到终点编号,输出路径

    while (G.vexs[end].path != -1) 
        {
            a[j] = G.vexs[end].path;
            end = G.vexs[end].path;
            j++;
        }

    至此最短路径查询完毕。

  • Dijkstra算法可以参考这个

  • 查询地点信息:将用户输入的字符串地点转换为地点编号,并输出介绍信息

    void search_introduction( Graph G)
    {
        string str;
        cout << "景点信息查询" << endl << "请输入要查询的地址:";
        cin >> str;
        int n = getnum(str, G);
        cout << G.vexs[n].name << "  " << G.vexs[n].introduction << endl;
    }

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

skywalkerTuT

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

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

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

打赏作者

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

抵扣说明:

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

余额充值