赛事管理系统

数据结构课程设计

背景

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

信息登录

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

信息查找

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

详细内容

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

赛事过程

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

地图信息

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

设计要求

  1. 赛事数据要求存入文件(txt或excel)并能读入查询;
  2. 赛地目的地查询,需提供目的地(建筑物)名称、代号、简介、两地之间路径长度等信息;
  3. 输入数据形式和范围:赛事相关数据可从键盘输入,或自文件导入。
  4. 界面要求:交互设计要合理,每个功能可以设计菜单,用户根据提示,完成相关功能的要求。

实现步骤提示

  1. 分析任务,进行模块划分。
  2. 定义数据结构,建议按照抽象数据类型的定义、表示和实现来描述,用类C语言(伪代码)来描述数据的存储表示和相应操作的具体实现过程。
  3. 设计合适的算法来实现其功能,并绘制函数调用关系图。

测试数据

要求使用全部合法数据,整体非法数据,局部非法数据。进行程序测试,以保证程序的健壮性。

基本构建
定义了一个名为Team的类,其中包含了6个私有属性:teamID、projectName、school、eventCategory、competitors和teacher。
class Team {
private String teamID;
private String projectName;
private String school;
private String eventCategory;
private String competitors;
private String teacher;

public Team(String ID, String project, String school, String category, String competitors, String teacher) {
    this.teamID = ID;
    this.projectName = project;
    this.school = school;
    this.eventCategory = category;
    this.competitors = competitors;
    this.teacher = teacher;
}

增加参赛队伍

private static void addTeam() {
Scanner input = new Scanner(System.in);
System.out.print("Enter team ID: ");
String teamID = input.nextLine();
System.out.print("Enter project name: ");
String projectName = input.nextLine();
System.out.print("Enter school: ");
String school = input.nextLine();
System.out.print("Enter event category: ");
String category = input.nextLine();
System.out.print("Enter competitors: ");
String competitors = input.nextLine();
System.out.print("Enter teacher: ");
String teacher = input.nextLine();
Team team = new Team(teamID, projectName, school, category, competitors, teacher);
teamList.add(team);
System.out.println(“Team added successfully.”);
}
删除参赛队伍
private static void deleteTeam() {
Scanner input = new Scanner(System.in);
System.out.print("Enter team ID: ");
String teamID = input.nextLine();
boolean found = false;
for (Team team : teamList) {
if (team.getTeamID().equals(teamID)) {

修改参赛队伍信息
teamList.remove(team);
found = true;
System.out.println(“Team deleted successfully.”);
break;
}
}
if (!found) {
System.out.println(“Team not found.”);
}
}
private static void updateTeam() {
Scanner input = new Scanner(System.in);
System.out.print("Enter team ID: ");
String teamID = input.nextLine();
boolean found = false;
for (Team team : teamList) {
if (team.getTeamID().equals(teamID)) {
System.out.println("Current project name: " + team.getProjectName());
System.out.print("Enter new project name (press ENTER to skip): ");
String projectName = input.nextLine();
if (!projectName.isEmpty()) {
team.setProjectName(projectName);
}

显示所有参赛队伍的赛事数据

private static void displayTeam() {
System.out.printf(“%-10s%-20s%-20s%-15s%-20s%-20s%n”, “Team ID”, “Project Name”, “School”, “Event Category”, “Competitors”, “Teacher”);
for (Team team : teamList) {
System.out.println(team);
}
}
public static void main(String… args) {
主函数,提供菜单选择和程序的控制流
Scanner input = new Scanner(System.in);
try {
do {
System.out.println(“\nEvent Management System Main Menu”);
System.out.println(“1. Add Team”);
System.out.println(“2. Delete Team”);
System.out.println(“3. Update Team”);
System.out.println(“4. Display All Teams”);
System.out.println(“5. Save and Exit”);

            System.out.print("\nEnter your choice (1-5): ");
            int choice = input.nextInt();
            input.nextLine(); // consume the newline character

构建二叉排序树
构建一个二叉排序树,并将参赛队伍按照编号插入到该二叉排序树中。
具体实现如下:

public class TeamNode { // 参赛队伍节点类
private Team team;
private TeamNode left;
private TeamNode right;

public TeamNode(Team team) {
    this.team = team;
}

public Team getTeam() {
    return team;
}

public void setTeam(Team team) {
    this.team = team;
}

public TeamNode getLeft() {
    return left;
}

public void setLeft(TeamNode left) {
    this.left = left;
}

public TeamNode getRight() {
    return right;
}

public void setRight(TeamNode right) {
    this.right = right;
}

}

public class BinarySearchTree { // 二叉排序树类
private TeamNode root;

public void insert(Team team) { // 将参赛队伍节点插入到二叉排序树中
    TeamNode node = new TeamNode(team);
    if (root == null) {
        root = node;
    } else {
        TeamNode current = root;
        while (true) {
            if (team.getId() < current.getTeam().getId()) {
                if (current.getLeft() == null) {
                    current.setLeft(node);
                    break;
                } else {
                    current = current.getLeft();
                }
            } else {
                if (current.getRight() == null) {
                    current.setRight(node);
                    break;
                } else {
                    current = current.getRight();
                }
            }
        }
    }
}

}
定义一个 TeamNode 类表示参赛队伍节点,在其基础上构建了一个 BinarySearchTree 类表示二叉排序树。在 BinarySearchTree 类中,我们实现了 insert 方法将参赛队伍节点插入到二叉排序树中。
实现查找功能
接下来,我们实现根据参赛队编号在二叉排序树中查找对应参赛队伍的基本信息。具体实现如下:

public class BinarySearchTree {
// …

public TeamNode search(int teamId) { // 在二叉排序树中查找参赛队伍
    TeamNode current = root;
    int depth = 0; // 记录查找深度
    while (current != null) {
        depth++;
        if (current.getTeam().getId() == teamId) {
            System.out.println("参赛作品名称:" + current.getTeam().getName()); // 输出参赛作品名称
            System.out.println("参赛学校:" + current.getTeam().getSchool()); // 输出参赛学校
            System.out.println("赛事类别:" + current.getTeam().getCategory()); // 输出赛事类别
            System.out.println("参赛者:" + current.getTeam().getMembers()); // 输出参赛者
            System.out.println("指导老师:" + current.getTeam().getTeacher()); // 输出指导老师
            System.out.println("查找成功!");
            System.out.println("平均查找长度ASL:" + (double) depth / count); // 输出查找成功时的平均查找长度ASL
            return current;
        } else if (current.getTeam().getId() > teamId) {
            current = current.getLeft();
        } else {
            current = current.getRight();
        }
    }
    System.out.println("查找失败!");
    return null;
}

}
定义 search 方法用于在二叉排序树中查找对应参赛队伍。在查找过程中,我们记录查找深度,并在查找成功时输出相应的参赛队伍基本信息和平均查找长度ASL。如果未找到对应参赛队伍,则输出“查找失败!”。
输出查找成功时的平均查找长度ASL
为了计算平均查找长度ASL,我们需要记录查找次数。在 BinarySearchTree 类中,我们添加了一个 count 属性表示查找次数:

private static Team insert(Team root, Team team, int level) {
if (root == null) {
team.setLevel(level + 1);
return team;
}
if (Integer.parseInt(team.getTeamId()) < Integer.parseInt(root.getTeamId())) {
root.setLeft(insert(root.getLeft(), team, level + 1), level + 1);
} else {
root.setRight(insert(root.getRight(), team, level + 1), level + 1);
}
return root;
}

private void setLevel(int level) {
this.level = level;
}

private static Team search(Team root, String teamId) {
if (root == null || root.getTeamId().equals(teamId)) {
return root;
}
if (Integer.parseInt(teamId) < Integer.parseInt(root.getTeamId())) {
return search(root.getLeft(), teamId);
} else {
return search(root.getRight(), teamId);
}
}
Stack stack = new Stack<>();
stack.push(root);

while (!stack.isEmpty()) {
TreeNode node = stack.pop();
if (node != null) {
// 访问根节点
levelSum += node.level;
// 累加查找过程中的层数
// 先将右子节点压入栈中,再将左子节点压入栈中,保证先遍历左子树
if (node.right != null) {
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
}
}
}
double aslSuccess = (double)levelSum / (double) this.nodeNum;
System.out.println("成功ASL =(double)levelSum / (double) nodeNum = "+aslSuccess);}

计算ASL的表达式为:ASL = (1 * n1 + 2 * n2 + 3 * n3 + … + k * nk) / N,其中ni表示查找长度为i的节点数,k表示最大查找长度,N表示总节点数。在查找过程中记录每个节点的查找长度,最后统计节点数和查找长度的乘积并除以总节点数即可得到ASL的值。
基本实现
在这里插入图片描述
在这里插入图片描述
参赛团队查询
可以将参赛学校名称作为键,将所有属于该学校的参赛团队作为值存储在列表中。然后,当用户输入要查询的学校名称时,我们可以在列表中查找该键对应的值,即该学校参赛的所有团队。在输出参赛团队时,我们需要按参赛队编号进行排序。选择排序是一种简单的排序算法,它的基本思想是每次从未排序的元素中选择最小的元素,放到已排序的元素末尾。选择排序的时间复杂度为O(n^2),因此它并不是一个高效的排序算法。但是,选择排序的实现简单,代码易于理解,因此在数据规模较小的情况下,选择排序是一种不错的选择。
选择排序:
searchAnsList.sort(new Comparator() {
@Override
public int compare(Team o1, Team o2) {
char[] e1 = new char[0];
char[] e2 = new char[0];
e1 = o1.getCategory().toCharArray();
e2 = o2.getCategory().toCharArray();
int len = e1.length;
int ret = -1;
if (e1.length > e2.length){
len = e2.length;
ret = 1;
}
for (int i = 0; i < len; i++) {
int i1 = e1[i];
int i2 = e2[i];
if (i1 == i2){
continue;
}else if (i1 > i2){
return 1;
}else {
return -1;
}
}
if (e1.length == e2.length){
return 0;
}
return ret;
}
决赛叫号系统
为了模拟决赛叫号系统,我们可以使用队列来管理参赛队伍的进场顺序。具体地,我们为每个决赛室都创建一个队列,每当一个参赛队伍被叫号时,就将其加入相应决赛室的队列中。然后,我们按照顺序遍历所有决赛室的队列,将队首的参赛队伍进场比赛。
基本分类
class Data{
public static final String[][] categoryList =
{
{“大数据实践”,“数据可视化”,“信息图形设计”,“交互信息设计”,“数据可视化”},
{“人工智能实践赛”,“计算机基础与应用类课程微课”,“虚拟实验平台”},
{“动态信息影像(MG动画)”,“动画”,“纪录片”,“数字短片”,“微电影”,“新媒体漫画”},
{“产品设计”,“环境设计”,“平面设计”,“交互媒体设计”,“游戏设计”,“虚拟现实VR与增强现实AR”},
{“Web应用与开发”,“管理信息系统”,“算法设计与应用”,“移动应用开发”,“移动应用开发(非游戏类)”},
{“医药卫生”,“数字生活”,“运动健身”,“城市管理”,“行业应用”},
{“汉语言文学”,“中、小学数学或自然科学课程微课”}
};
}

七个队列输出
public class Event {
public void run(List teamList) {
List<List> list = new ArrayList<>();
for (int i = 0; i < Data.categoryList.length; i++) {
list.add(new ArrayList<>());
}
for (Team team : teamList) {
String category = team.getCategory();
for (int i = 0; i < Data.categoryList.length; i++) {
for (int j = 0; j < Data.categoryList[i].length; j++) {
if (Data.categoryList[i][j].equals(category)){
list.get(i).add(team);
}
}
}
}
int time;
for (int i = 0; i < list.size(); i++) {
System.out.println(“--------------第”+(i+1)+“组进场模拟---------------”);
time = 3000000;
for (int j = 0; j < list.get(i).size(); j++) {
Team team = list.get(i).get(j);
System.out.print(“队号: “);
System.out.print(team.getNum());
System.out.print(”\t”);
System.out.print(team.getCategory());
System.out.print(“\t”);
System.out.print(team.getParticipants());
System.out.print(“\t准备进场\t”);
System.out.println(new SimpleDateFormat().format(new Date(time)).replace(“1970/1/1”,“”));
time+= 250000;
}
}
}
}
校园导游咨询
求解出两个顶点之间的最短路径。根据数据结构课程所学知识,有多种经典算法可以解决最短路径问题,包括Dijkstra算法,Floyd-Warshell算法,Bellman-Ford算法和深度优先遍历。不同是算法有不同的算法复杂度,考虑到校园中道路没有负权边,即算法均可解决最短路径问题。
我选择Dijkstra算法,即从一个结点出发到其它所有结点的最短路径,算法的时间复杂度为O(n2) ,在实现Dijkstra算法时,可以使用优先队列来维护未计算出最短路径的顶点。优先队列中的元素按照距离起点的距离排序,每次从队首取出距离起点最近的顶点进行计算。
初始化顶点常量
static {

nodeList[0] = new Node(1,"3号组团","学生宿舍");
nodeList[1] = new Node(2,"西苑食堂","学生食堂");
nodeList[2] = new Node(3,"明德楼","教学楼");
nodeList[3] = new Node(4,"文体中心","体育活动");
nodeList[4] = new Node(5,"西操场","体育活动");
nodeList[5] = new Node(6,"笃学楼","上课");
nodeList[6] = new Node(7,"东操场","体育活动");
nodeList[7] = new Node(8,"东苑食堂","学生食堂");
nodeList[8] = new Node(9,"图书馆","读书,自习");
nodeList[9] = new Node(10,"文理大楼","教学,办公综合大楼");
nodeList[10] = new Node(11,"计算机学院","学院楼");
nodeList[11] = new Node(12,"行政大楼","办公大楼");
for (int i = 0; i < graph.length; i++) {
    for (int j = 0; j < graph[0].length; j++) {
        //初始化为全不连通
        graph[i][j] = MAX_INT;
    }
}
linkEdge(0,1,110);
linkEdge(0,3,250);
linkEdge(1,3,200);
linkEdge(1,2,130);
linkEdge(1,4,120);
linkEdge(2,4,50);
linkEdge(2,9,100);
linkEdge(3,4,100);
linkEdge(3,6,210);
linkEdge(4,5,135);
linkEdge(4,9,100);
linkEdge(5,6,100);
linkEdge(5,7,190);
linkEdge(5,8,135);
linkEdge(5,9,120);
linkEdge(5,10,170);
linkEdge(6,7,125);
linkEdge(7,8,190);
linkEdge(8,11,210);
linkEdge(9,10,50);
linkEdge(10,11,250);

}
Dijkstra算法:
private void dijkstra(Integer source) {
HashMap<Integer, Way> s = new HashMap<>();
HashMap<Integer, Way> vs = new HashMap<>();
s.put(source,new Way(0,(source+1)+“->”));
for (int i = 0; i < vertexNum; i++) {
if(i == source){
continue;
}
vs.put(i,new Way(MapC.MAX_INT,“”));
}
校园无向图:
校园无向图

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
目 录 1 1 奥运会赛事管理管理系统需求分析 1 1.1开发背景 1 1.2 系统主要业务分析 2 1.2.1 运动员信息管理业务分析 2 1.2.2 运动队信息管理业务分析 2 1.2.3比赛项目管理业务分析 3 1.2.4 计分项目管理业务分析 3 1.2.5 裁判员管理业务分析 4 1.2.6项目类型管理业务分析 4 1.2.7国家管理业务分析 5 1.2.8赛事地点管理业务分析 5 1.2.9赛事信息管理业务分析 5 1.2.10赛事纪录管理业务分析 6 1.2.11运动员参加项目管理业务分析 6 1.2.12赛事项目对应管理业务分析 7 1.2.13赛事裁判对应管理业务分析 7 1.3 系统功能需求分析 8 1.3.1运动员信息管理需求分析 8 1.3.2运动队信息管理需求分析 9 1.3.3比赛项目信息管理需求分析 10 1.3.4计分项目信息管理需求分析 11 1.3.5裁判员信息管理需求分析 12 1.3.6项目类型管理功能分析 12 1.3.7国家管理功能分析 13 1.3.8赛事地点管理功能分析 13 1.3.9赛事记录管理功能分析 14 1.3.10赛事信息管理功能分析 14 1.3.11运动员参加项目管理需求分析 15 1.3.12赛事项目对应管理需求分析 16 1.3.13赛事裁判对应管理需求分析 17 1.3.14查询、审核需求分析 18 1.3.15评分需求分析 18 1.4 系统数据模型 19 1.5 数据字典 24 2 奥运会赛事管理系统逻辑结构设计 33 2.1 系统模块划分 33 2.2 数据库逻辑结构设计 34 3 奥运会赛事管理系统功能设计 36 3.1.1 裁判信息增加操作 36 3.1.2裁判信息删除操作 36 3.1.3裁判信息修改操作 36 3.1.4裁判信息查询操作 37 3.1.5赛事信息增加操作 37 3.1.6赛事信息删除操作 37 3.1.7赛事信息修改操作 37 3.1.8赛事记录增加操作 37 3.1.9赛事记录删除操作 38 3.1.10赛事记录修改操作 38 3.1.11赛事地点增加操作 38 3.1.12赛事地点删除操作 38 3.1.13赛事地点修改操作 38 3.1.14赛事裁判对应表增加操作 39 3.1.15赛事裁判对应表删除操作 39 3.1.16赛事信息查询操作 39 3.1.17赛事记录查询操作 39 3.1.18赛事地点查询操作 39 3.1.19赛事裁判对应表查询操作 40 3.1.20保证同一时间只能举行一个项目的触发器 40 3.1.21 比赛项目增加操作(项目编号、项目类型编号、项目名称) 40 3.1.22 比赛项目删除操作(项目编号、项目类型编号、项目名称) 40 3.1.23比赛项目修改操作(项目编号、项目类型编号、项目名称) 41 3.1.24比赛项目查询操作(项目编号、项目类型编号、项目名称) 41 3.1.38运动员增加操作 43 3.1.39运动员删除操作 44 3.1.40运动员修改操作 44 3.1.41运动员查询操作 44 3.1.42国家增加操作 45 3.1.43国家删除操作 45 3.1.44国家修改操作 45 3.1.45国家查询操作 45 3.1.46计分项目增加操作 45 3.1.47计分项目删除操作 46 3.1.48计分项目修改操作 46 3.1.49计分项目查询操作 46 3.1.50运动员参加项目增加操作 46 3.1.51运动员参加项目删除操作 47 3.1.52运动员参加项目查询操作 47 3.1.53place的删除触发器 47 4 课程设计总结 47 4.1 总结 47 4.2 展望 48

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值