数据结构课设——赛事管理系统

问题描述

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

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

(2)从team.txt中读取参赛队伍的基本信息,实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。
(3)能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队),即,根据提示输入参赛学校名称(赛事类别),若查找成功,输出该学校参赛的(该赛事类别的)所有团队的基本信息,输出的参赛团队按赛事类别有序输出。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)

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

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

基本要求

(1)赛事数据要求存入文件(txt或excel)并能读入查询;

(2)赛地目的地查询,需提供目的地(建筑物)名称、代号、简介、两地之间路径长度等信息;

(3)输入数据形式和范围:赛事相关数据可从键盘输入,或自文件导入。

(4)界面要求:交互设计要合理,每个功能可以设计菜单,用户根据提示,完成相关功能的要求。
 

一、任务点1:参赛队伍管理

1、问题分析

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

2、算法设计

(1)首先,打印出赛事信息管理系统的菜单选项,包括增加新的参赛队伍信息、删除参赛队伍信息、修改参赛队伍信息以及退出管理信息系统选项。

(2)接下来,用户被要求输入要执行的操作编号。

(3)进入while循环,只要用户选择的操作编号不是0,就会一直执行循环内的代码。

如果用户选择的操作是1,表示要增加新的参赛队伍信息。在这种情况下,用户被要求输入新队伍的各项基本信息,并创建一个新的Team对象。然后,将该对象添加到teams列表中,并提示用户选择下一个操作。

如果用户选择的操作是2,表示要删除参赛队伍信息。在这种情况下,用户需要输入要删除的参赛队伍的编号。然后,遍历teams列表,查找与输入编号匹配的参赛队伍对象。如果找到匹配的参赛队伍,则将其从列表中删除,并显示删除成功的消息;否则,显示查找失败的消息。最后,提示用户选择下一个操作。

如果用户选择的操作是3,表示要修改参赛队伍信息。在这种情况下,用户需要输入要修改的参赛队伍的编号。然后,遍历teams列表,查找与输入编号匹配的参赛队伍对象。如果找到匹配的参赛队伍,则提示用户输入修改后的队伍基本信息,并更新该参赛队伍的属性值。最后,显示修改成功或查找失败的消息,并提示用户选择下一个操作。

如果用户输入的操作编号不是1、2、3或0,则显示输入有误的消息,并要求用户重新输入操作编号。

当用户输入的操作编号为0时,退出循环,结束程序的执行。

3、算法实现

设置一个Team类
public class Team {
    int ID; //作品编号
    String Name; //作品名称
    String Category; //类别
    String Student; //参赛者
    String Teacher; //指导老师
    String University; //大学
    int Finalneedtime;
    Team(){
        Finalneedtime=(int)(Math.random()*10+5);
    }
}
部分主要代码(完整代码见最后):
static void Operateteams(){
    System.out.println("-----------------赛事信息管理系统--------------------");
    System.out.println("1-增加新的参赛队伍信息");
    System.out.println("2-删除参赛队伍信息");
    System.out.println("3-修改参赛队伍信息");
    System.out.println("0-退出管理信息系统");
    System.out.println("--------------------------------------------------");
    System.out.println("请输入你想进行的操作所对应的编号");
    int p;
    p=sc.nextInt();
    while (p!=0){
        if(p==1)
        {
            Team newteam=new Team();
            System.out.println("请输入新添加的队伍基本信息");
            System.out.print("请输入新的参赛队伍编号:");
            newteam.ID=sc.nextInt();
            System.out.print("请输入新队伍的参赛作品名称:");
            newteam.Name=sc.next();
            System.out.print("请输入新队伍的赛事类别:");
            newteam.Category =sc.next();
            System.out.print("请输入新队伍参赛者姓名:");
            newteam.Student=sc.next();
            System.out.print("请输入新队伍指导老师姓名:");
            newteam.Teacher=sc.next();
            System.out.print("请输入新队伍的学校:");
            newteam.University=sc.next();
            teams.add(newteam);
            System.out.println("请选择选择下一个操作(输入0可以结束):");
            p=sc.nextInt();
        }

4、实验结果

增加队伍:

 

删除队伍

修改队伍:

 

二、任务点2:基于二叉排序树的查找

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

1、问题分析

首先,需要将team.txt文件中的数据读取并构建二叉排序树(这里我选择读取excel表格中的数据进行处理),以便于后面的查询。从根节点开始,对于每个节点,如果查找关键字比节点关键字小,就进入左子树,否则进入右子树,直到找到查找关键字,或者找不到为止。

当查询到目标队伍时,输出该队伍的参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息。同时,通过公式计算出平均查找长度ASL,即从根节点到查找到的目标节点的平均路径长度。

2、算法设计

(1)首先,打印出文件录入查询系统的菜单选项,包括基于二叉排序树的根据赛队编号查询并输出信息,并求查找成功的平均查找长度ASL,以及退出选项。

(2)接下来,输出正在对文件中信息建立二叉排序树的提示信息。

声明变量p来接收用户输入的操作编号。

(3)使用循环,只要用户选择的操作编号不是0,就会一直执行循环内的代码。

如果用户选择的操作是1,表示根据赛队编号进行查询。用户被要求输入要查找的参赛队伍编号。接着,遍历teams列表,并将每个参赛队伍的信息插入到二叉排序树中。然后,执行查找功能以查找指定编号的参赛队伍。如果查找失败,则输出查找失败的消息;否则,输出查找成功的消息,并显示查找到的参赛队伍的详细信息。最后,计算文件信息建立的二叉排序树的平均成功查找长度ASL,并显示该值。

如果用户输入的操作编号不是1或0,则显示输入有误的消息,并要求用户重新输入操作编号。

当用户输入的操作编号为0时,退出循环,结束程序的执行。

3、算法实现

1、建立二叉树
for(int i=0;i< teams.size();i++){
    Team t= (Team) teams.get(i);
    tree.insert(t.ID,t.Name,t.Category,t.Student,t.Teacher,t.University);
}
2、ASL的计算(程序检查时ASL的计算有误,现修改如下)
public int findASL(int key) {
        Node current = root;

        while (current.data != key) {
            ASL++;
            if (key > current.data) {

                current = current.right;
            } else {
                current = current.left;
            }
            if (current == null) {
                return 0;
            }
        }
        ASL++;   //查程序时发现我寻找的是目标节点上一个节点的深度,在这儿进行ASL++的操作,便可以解决ASL计算错误的问题。
        return ASL;
    }

4、实验结果

代码修改前:

 

改正后:

三、任务点三:参赛团队查询

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

1、问题分析

对于排序算法的选择,每个算法都有其自身的特点和适用场景,比如:选择排序在数据量比较少的情况下效率较高,但是在数据量大的情况下其时间复杂度较高;插入排序在数据量有序或近乎有序时效率较高;希尔排序可根据不同的增量序列来逐步缩小排序间隔,从而减少排序的比较次数和移动次数;归并排序使用分治法,将数据分成较小的部分逐步排序,然后将各个有序的部分合并起来,适用于大数据量和跨越式分布的数据;堆排序利用了二叉堆的特性,可以有效地实现排序。因此,你可以根据实际情况选择合适的排序算法,具体要选择哪个算法可以根据数据的实际情况和对速度、空间等方面的考虑进行选择。

对于查询结果的按照赛事类别进行排序,你可以使用排序算法来实现。具体来说,可以将团队信息存储在数组中,然后使用选择排序、插入排序、希尔排序、归并排序或堆排序等算法来对赛事类别进行排序,最终将排序后的结果输出即可。

2、算法设计

(1)首先,代码打印了赛事大类的列表,它包含了几个选项供用户选择操作。

(2)创建了一个名为"category"的ArrayList数组,长度为9,每个元素是一个ArrayList实例。这个数组用于将赛事按类别分组存储。

遍历名为"teams"的队伍列表中的每个队伍。

(3)根据队伍的"Category"属性将它们分别添加到"category"数组的不同位置。使用条件语句将每个队伍分组到特定的类别中。

用户被要求输入操作编号,并使用"sc.nextInt()"读取输入值。

进入while循环,只要用户输入的操作编号不为0,就会继续执行下面的代码。

(4)遍历"category"数组,通过对每个类别中的队伍列表调用“sort”方法来将队伍按照类别排序。

如果用户输入的操作编号是1,代码会要求用户输入学校名称,并在匹配到的队伍中输出队伍的信息,包括队伍编号、作品名称、学校、赛事类别、参赛者和指导教师。

在操作结束后,用户被要求选择下一个操作,如果已经尝试完毕,可以输入0来结束循环;否则,继续读取用户的输入。

如果用户输入的操作编号大于1或小于0,则输出错误信息,要求重新输入操作编号。

循环结束后,代码执行完毕。

3、算法实现

1、将赛事按类别分到不同的组别中(部分主要代码)
ArrayList catagory[];
catagory=new ArrayList[9];
for(int i=0;i<9;i++){
    catagory[i]= new ArrayList();
}
for (int i=0;i<teams.size();i++){
    Team t= (Team) teams.get(i);

    if(Objects.equals(t.Category, "大数据实践")){
        catagory[0].add(t);

        continue;
    }
    if(Objects.equals(t.Category, "信息图形设计") || Objects.equals(t.Category, "动态信息影像(MG动画)") || Objects.equals(t.Category, "交互信息设计") || Objects.equals(t.Category, "数据可视化")){
        catagory[1].add(t);

        continue;
    }
    if(Objects.equals(t.Category, "人工智能实践赛")){
        catagory[2].add(t);
        continue;
    }
    if(Objects.equals(t.Category, "Web应用与开发") || Objects.equals(t.Category, "管理信息系统") || Objects.equals(t.Category, "算法设计与应用") || Objects.equals(t.Category, "移动应用开发(非游戏类)") || Objects.equals(t.Category, "移动应用开发")){

        catagory[3].add(t);
        continue;
    }
    if(Objects.equals(t.Category, "医药卫生") || Objects.equals(t.Category, "数字生活") || Objects.equals(t.Category, "运动健身") || Objects.equals(t.Category, "城市管理") || Objects.equals(t.Category, "行业应用")){

        catagory[4].add(t);
        continue;
    }
    if(Objects.equals(t.Category, "动画") || Objects.equals(t.Category, "纪录片") || Objects.equals(t.Category, "数字短片") || Objects.equals(t.Category, "微电影") || Objects.equals(t.Category, "新媒体漫画")){

        catagory[5].add(t);
        continue;
    }
    if(Objects.equals(t.Category, "产品设计") || Objects.equals(t.Category, "环境设计") || Objects.equals(t.Category, "平面设计")){

        catagory[6].add(t);
        continue;
    }
    if(Objects.equals(t.Category, "交互媒体设计") || Objects.equals(t.Category, "游戏设计") || Objects.equals(t.Category, "虚拟现实VR与增强现实AR" )){

        catagory[7].add(t);
        continue;
    }
    if(Objects.equals(t.Category, "汉语言文学") || Objects.equals(t.Category, "计算机基础与应用类课程微课") || Objects.equals(t.Category, "虚拟实验平台") || Objects.equals(t.Category, "中、小学数学或自然科学课程微课") || Objects.equals(t.Category, "计算机基础与应用类课程微课")){
        catagory[8].add(t);

        continue;
    }
}

3、实验结果

四、任务点四:决赛叫号系统模拟

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

1、问题分析

我们可以使用一个包含参赛队信息的列表来表示参赛队,然后按照赛事类别将他们分配到相应的决赛室。接着,我们可以使用一个队列来表示每个决赛室参赛队进场的顺序,决赛室依次从队头取出队首的参赛队进场,比赛结束后将该队的下一个队员加入队尾,这样便能够确保进场秩序和叫号顺序一致。

2、算法设计

(1)首先,定义了一个长度为9的ArrayList数组catagory和一个长度为9的Queue数组room,用于存储队伍信息和每个赛事对应的房间队列。

(2)使用for循环,将每个赛事按照类别分别存入不同的组别(ArrayList)和房间队列(PriorityQueue)。

(3)遍历所有的队伍信息,根据队伍的赛事类别将其放入对应的房间队列中。

在一个while循环中,只要还有队伍未被安排到房间中,就依次输出队伍信息。

输出队伍信息时,首先输出对应赛事大类的名称,然后输出房间号和参赛队伍编号。

从每个房间队列中取出一个队伍,并输出其赛事大类、房间号和队伍编号。

当所有房间队列都为空时,跳出循环。

最后输出一条信息表示叫号结束,并返回到程序的主目录。

2、算法实现

部分主要代码

static void Finalimitate(){
    ArrayList catagory[];
    catagory=new ArrayList[9];
    Queue room[]=new Queue[9];
    for(int i=0;i<9;i++){//将赛事按类别分到不同的组别中
        catagory[i]= new ArrayList();
        room[i]=new PriorityQueue<Team>(comID);
    }//将不同的类别分组
    for (int i=0;i<teams.size();i++){
        Team t= (Team) teams.get(i);

        if(Objects.equals(t.Category, "大数据实践")){
            room[0].add(t);
            continue;
        }
        if(Objects.equals(t.Category, "信息图形设计") || Objects.equals(t.Category, "动态信息影像(MG动画)") || Objects.equals(t.Category, "交互信息设计") || Objects.equals(t.Category, "数据可视化")){
            room[1].add(t);
            continue;
        }
        if(Objects.equals(t.Category, "人工智能实践赛")){
            room[2].add(t);
            continue;
        }
……
while(!room[0].isEmpty()||!room[1].isEmpty()||!room[2].isEmpty()||!room[3].isEmpty()||!room[4].isEmpty()||!room[5].isEmpty()||!room[6].isEmpty()||!room[7].isEmpty()||!room[8].isEmpty()){
        System.out.println("请以下队伍准备进入赛场");
        System.out.println();
        System.out.println("赛事大类         "+"   房间号         "+"参赛队编号");
        for (int i=0;i<9;i++){

            if(i==0&&!room[0].isEmpty())System.out.print("大数据应用         ");
            if(i==1&&!room[1].isEmpty())System.out.print("信息可视化设计       ");
            if(i==2&&!room[2].isEmpty())System.out.print("人工智能应用        ");
            if(i==3&&!room[3].isEmpty())System.out.print("软件应用与开发       ");
            if(i==4&&!room[4].isEmpty())System.out.print("物联网应用          ");
            if(i==5&&!room[5].isEmpty())System.out.print("数媒动漫与短片       ");
            if(i==6&&!room[6].isEmpty())System.out.print("数媒静态设计         ");
            if(i==7&&!room[7].isEmpty())System.out.print("数媒游戏与交互设计    ");
            if(i==8&&!room[8].isEmpty())System.out.print("微课与教学辅助       ");
            Team t= (Team) room[i].poll();
            if(t!=null)System.out.println("  "+(i+1)+"         "+ t.ID);

    }
    }

    System.out.println(" ");
    System.out.println("叫号结束,返回目录");
}

3、实验结果

 

五、任务点五:基于校园地图的导航系统

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

1、数据结构的选择和概要设计

Floyd算法是一种图论算法,用于求解任意两点之间的最短路径。它的核心思想是动态规划,通过不断更新节点之间的距离,最终得到最短路径。本任务点我决定采用Floyd算法进行设计。

2、图例

 

 

3、算法设计

1、类
class Graph {
    protected List<String> vertex;//存放顶点
    protected int[][] edges;//存放边
    protected boolean[] isVisited;//是否被访问
    protected int numOfEdges;
    int [][] accessible;
    public Graph(int n) {
        this.vertex = new ArrayList<>(n);
        this.edges = new int[n][n];
        this.isVisited = new boolean[n];
        this.accessible=new int[10][10];
    }
    // 1. 获取节点个数
    protected int getNumOfVertex();
    // 2. 打印邻接矩阵
    protected void printGraph();
    // 3. 获取边的数目
    protected int getNumOfEdges(); 
    // 4. 获取某条边的权值
    protected int getWeightOfEdges(int v1, int v2); 
    // 5. 添加节点
    protected void addVertex(String v) ;
    // 6. 添加边(双向)
    protected void addEdge(int v1, int v2, int weight); 
    // 7.获取顶点索引对应的值
    protected String getValueByIndex(int i);
}

4、算法实现

(1)floyd算法
static void floyd(int[][] graph,int len,String[] vax,int[][] path){
    for (int k = 0; k < len; k++)
        for (int i = 0; i < len; i++)
            for (int j = 0; j < len; j++)
                if (graph[i][j] > graph[i][k]+graph[k][j]){
                    graph[i][j] = graph[i][k] + graph[k][j];
                    //path记录路径
                    path[i][j]=path[i][k];
                }
}
(2)打印最短路径
static void print_road(int[][] graph,int[][]path,String[] vax,int u,int v){
    //打印出最短路径
    int tmp=u;
    Scanner sc = new Scanner(System.in);
    int m = sc.nextInt();
    System.out.print("从起点到终点的最短路径为:");
    System.out.print(vax[m]+"-->");
    while(!vax[tmp].equals(vax[v]))
    {
        System.out.print(vax[path[tmp][v]]);
        tmp=path[tmp][v];
        if(!vax[tmp].equals(vax[v]))
            System.out.print("-->");
    }

    System.out.println();
    System.out.println("最短路线长度是:"+graph[u][v]);
}

(3)创建无向图
static int[][] creat_Graph(int len,int[][] path){
    //创建邻接矩阵
    int m=99999;
    int[][] graph=new int[len][len];
    //初始化邻接矩阵
    for(int i=0;i<graph.length;i++)
        for(int j=0;j<graph[0].length;j++){
            if(i==j)
                graph[i][j]=0;
            else
                graph[i][j]=m;
            //将path初始化为j
            path[i][j]=j;
        }
    //根据图输入数据
    //A的子路径
    graph[0][1]=100;
    graph[0][3]=200;
    //B的子路径
    graph[1][2]=80;
    graph[1][3]=150;
    //C的子路径
    graph[2][4]=120;
    graph[2][5]=110;
    //D的子路径
    graph[3][4]=50;
    //E的子路径
    graph[4][7]=150;
    graph[4][8]=230;
    //F的子路径
    graph[5][6]=80;
    graph[5][7]=60;
    //G的子路径
    graph[6][9]=100;
    //H的子路径
    graph[7][8]=90;
    graph[7][9]=70;
    //I的子路径
    graph[8][9]=50;
    return graph;
}

5、实验结果

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值