本次课程设计要求协助中国大学生计算机设计大赛江苏省组委会,设计一款赛事管理系统,实现赛务相关的数据管理及信息服务,该系统能够为省级赛事管理解决以下问题:
(1)从team.txt中读取参赛队伍的基本信息,能够管理各参赛队的基本信息(包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项(参见大赛官网jsjds.blcu.edu.cn);包括增加、删除、修改参赛队伍的信息。
该问题需要实现:从team.txt中读取参赛队伍的基本信息,能够管理各参赛队的基本信息,包括增加、删除、修改参赛队伍的信息等。具体的编程实现需要按以下步骤进行:
1. 定义参赛队的数据结构。根据题目要求,参赛队的基本信息包含参赛队编号、参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息,可以定义一个包含这些信息的结构体或类。
2. 读取team.txt文件中的参赛队信息。可以使用Java的IO技术,在程序启动时从team.txt文件中读取参赛队的基本信息,并存储到程序中。可以采用ArrayList等Java集合来存储参赛队信息。
3. 实现增加参赛队伍信息的功能。可以提示用户输入新的参赛队伍的信息,然后将新的参赛队伍信息添加到参赛队伍集合中。
4. 实现删除参赛队伍信息的功能。可以提示用户输入需要删除的参赛队伍的编号,然后在参赛队伍集合中查找该编号对应的参赛队伍信息,并将其删除。
5. 实现修改参赛队伍信息的功能。可以提示用户输入需要修改的参赛队伍的编号,然后在参赛队伍集合中查找该编号对应的参赛队伍信息。然后,提示用户输入修改后的参赛队伍信息,并将其更新到参赛队伍集合中。
6. 实现保存参赛队伍信息的功能。在程序结束时,将参赛队伍集合中的信息保存到team.txt文件中。
对于该问题,要设计一个适合的数据结构来存储参赛队伍的基本信息,包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师。显然可以设计一个Team类,里面包含上述信息。我们要对team.txt的数据的信息进行抓取提取,并放到合适的容器中。这里我用的是List集合列表。
public class Team {
// 参赛队伍编号
private int teamNumber;
// 项目名称
private String projectName;
// 学校名称
private String schoolName;
// 赛事类别
private String eventCategory;
// 参赛队员
private String participants;
// 指导老师
private String guideTeacher;
}
参赛队伍管理的实现类和接口TeamService和TeamServiceImpl
其中接口TeamService
/**
* 对参赛队进行 CRUD (增删改查)操作
*/
public interface TeamService { //接口
/**
* 新增参赛队伍信息
* @param team 要添加的参赛队伍信息
*/
void addTeamInfo(Team team);
/**
* 根据参赛队伍编号删除参赛队伍信息
* @param teamNumber 要删除的参赛队伍编号
*/
void deleteTeamInfo(Integer teamNumber);
/**
* 根据参赛队伍编号查看参赛队伍信息
* @param team 要修改的参赛队伍信息
*/
void updateTeamInfo(Team team);
/**
* 根据参赛队伍编号查看参赛队伍信息
* @param teamNumber 要查看的参赛队伍编号
*/
void searchTeamByNumber(int teamNumber);
/**
* 根据学校名称查看参赛队伍信息
* @param schoolName 要查看的学校名称
*/
void searchTeamsBySchoolName(String schoolName);
/**
* 根据赛事类别查看参赛队伍信息
* @param eventCategory 要查看的赛事类别
*/
void searchTeamsByEventCategory(String eventCategory);
List<Team> getByEventCategory(String eventCategory);
(2)从team.txt中读取参赛队伍的基本信息,实现基于二叉排序树的查找。根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。
在BST包中设置两个类
BST和BSTNode
BSTNode为一个节点类,其中有键值和参赛队伍的数据结构
/**
* 二叉搜索树(Binary Search Tree, BST)节点类,其中包含键值和参赛队伍 {@link Team} 数据
*/
@Data
@Builder
public class BSTNode {
// 键值
private int key;
// 参赛队伍
private Team team;
// 左子节点
private BSTNode left;
// 右子节点
private BSTNode right;
}
BST类 二叉搜索树(Binary Search Tree, BST)类 说明:二叉搜索树是一种特殊的二叉树,它的左子树的键值小于根节点的键值,右子树的键值大于根节点的键值
以下为二叉搜索树的算法和设计
public class BST {
// 根节点
private BSTNode root;
// 路径长度(查找时经过的节点数)
private int pathLength;
// 节点数
private int numNodes;
/**
* 填充二叉搜索树
*/
public void insert(int teamNumber, Team team){
// 如果根节点为空,则将新节点作为根节点
if (root == null) {
// 创建新节点,并将其作为根节点
root = BSTNode.builder().key(teamNumber).team(team).build();
// 节点数加一
numNodes++;
return;
}
// 如果根节点不为空,则从根节点开始查找要插入的位置
insert(root,teamNumber,team);
}
/**
* 该方法用于向二叉搜索树中插入节点
* @param node 二叉搜索树的根节点
* @param key 键值
* @param team 参赛队伍
*/
private void insert(BSTNode node,int key,Team team) {
// 如果节点的键值大于要插入的键值,则在左子树中插入
if (node.getKey() > key) {
// 如果左子节点为空,则将新节点作为左子节点
if (node.getLeft() == null) {
// 创建新节点,并将其作为左子节点
node.setLeft(BSTNode.builder().key(key).team(team).build());
// 节点数加一
numNodes++;
return;
}
// 如果左子节点不为空,则从左子节点开始查找要插入的位置
insert(node.getLeft(), key, team);
}
// 如果节点的键值小于要插入的键值,则在右子树中插入
if (node.getKey() < key) {
// 如果右子节点为空,则将新节点作为右子节点
if (node.getRight() == null) {
// 创建新节点,并将其作为右子节点
node.setRight(BSTNode.builder().key(key).team(team).build());
// 节点数加一
numNodes++;
return;
}
// 如果右子节点不为空,则从右子节点开始查找要插入的位置
insert(node.getRight(), key, team);
}
}
/**
* 该方法用于向二叉搜索树中插入节点
* @param key 键值
* @return 插入的节点
*/
public BSTNode search(int key){
// 重置路径长度
pathLength = 0;
return search(root,key);
}
/**
* 该方法用于在二叉搜索树中查找键值为 key 的节点
*
* @param node 二叉搜索树的根节点
* @param key 键值
* @return 键值为 key 的节点
*/
private BSTNode search(BSTNode node,int key){
// 路径长度加一
pathLength++;
// 如果节点为空或者节点的键值等于要查找的键值,则返回该节点
if (node == null || node.getKey() == key) {
return node;
}
// 如果节点的键值大于要查找的键值,则在左子树中查找
if (node.getKey() > key) {
return search(node.getLeft(), key);
}
// 如果节点的键值小于要查找的键值,则在右子树中查找
return search(node.getRight(), key);
}
/**
* 获取平均路径长度
* @return 平均路径长度
*/
//获取平均路径长度
public double getAveragePathLength(){
// 计算公式:路径长度 / 节点数
return (double) pathLength / numNodes;
}
}
(3)能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队),即根据提示输入参赛学校名称(赛事类别),若查找成功,输出该学校参赛的(该赛事类别的)所有团队的基本信息,输出的参赛团队按赛事类别有序输出。(排序算法可从选择排序、插入排序、希尔排序、归并排序、堆排序中任意选择,并为选择算法的原因做出说明。)
根据参赛队伍名称查看参赛队伍信息:这里我选择用用归并排序(Merge Sort)来进行赛事(eventCategory)的排序, 因为归并排序对于大的数据集来说非常高效,时间复杂度为O(n log n),并且它是稳定的排序算法, 这意味着相同的元素在排序后会保持原有的顺序。
下面给出了我设计的简易思路和部分代码
/**
* 归并排序
* @param teams 要排序的参赛队伍信息
* @return 排序后的参赛队伍信息
*/
private static List<Team> mergeSort(List<Team> teams) {
// 如果列表为空或者只有一个元素,则直接返回
if (teams.size() < 2) {
return teams;
}
// 将列表分为两部分
int midIndex = teams.size() / 2;
// 左边的列表
List<Team> left = new ArrayList<>(teams.subList(0, midIndex));
// 右边的列表
List<Team> right = new ArrayList<>(teams.subList(midIndex, teams.size()));
// 调用递归函数,分别对左右两边的列表进行排序
return merge(mergeSort(left), mergeSort(right));
}
(4)为省赛现场设计一个决赛叫号系统。所有参赛队按赛事组织文件中的赛事类别分到9个决赛室,决赛室按顺序叫号,被叫号参赛队进场,比赛结束后,下一参赛队才能进赛场。请模拟决赛叫号系统,演示省赛现场各决赛室的参赛队进场情况。(模拟时,要能直观展示叫号顺序与进场秩序一致)
设计思路
将方法和执行类分开,在方法内不用写入具体的入队和出队操作,在每次调用取号操作时内部的变量内容都会加一,每次调用叫号操作时内部的变量内容都会减一,在执行类中用while语句包含着switch case语句来选择取号、叫号还是退出服务,来实现系统操作
这个实验用顺序队列比链式队列更加容易理解和实现,只需要用到顺序队列的思路,不需要写出集体的入队和出队操作来
提前写好无参构造函数,对所有可变变量赋值,在定义对象的时候使用无参构造函数,不要到后面实现的时候才另做赋值操作
mport java.util.Scanner;
class LinkedQueue {
private int front,rear; //声明队头和队尾
private int count; //声明承载记录总人数作用的变量
public static final int MAX = 100;//定义最大值
private final int[] arr = new int[MAX]; //确定数组的最大值
private int num; //用于承载队中人数随时变换的数据变量
public LinkedQueue() { //定义无参构造方法
}
public void GetNumber(LinkedQueue a){ //用于表达取号的方法
}
public void CallNumber(LinkedQueue a){ //用于表达叫号的方法
}
//以下为各个变量的getter和setter
public int getFront() {
return front;
}
public int getNum() {
return num;
}
public int getCount() {
return count;
}
//以下为判断方法
public boolean Full(){ //用于表达判断队满的方法
}
public boolean isEmpty() { //用于表达判空的方法
}
}
public class QueueOrder {
public static void main(String[] args){
switch (flag){
case 1: {
}
case 2:{
}
case 3:
scan.close();
return;
}
}
}
}
(5)赛事系统为参赛者提供赛地的校园导游程序,为参赛者提供各种路径导航的查询服务。以我校长山校区提供比赛场地为例,(请为参赛者提供不少于10个目标地的导航。可为参赛者提供校园地图中任意目标地(建筑物)相关信息的查询;提供任意两个目标地(建筑物)的导航查询,即查询任意两个目的地(建筑物)之间的一条最短路径。
迪杰斯特拉算法是从一个顶点到其余各顶点的最短路径算法,解决的是有权图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。迪杰斯特拉算法采用的是贪心策略,将Graph中的节点集分为最短路径计算完成的节点集S和未计算完成的节点集T,每次将从T中挑选V0->Vt最小的节点Vt加入S,并更新V0经由Vt到T中剩余节点的更短距离,直到T中的节点全部加入S中,它贪心就贪心在每次都选择一个距离源点最近的节点加入最短路径节点集合。迪杰斯特拉算法只支持非负权图,它计算的是单源最短路径,即单个源点到剩余节点的最短路径,时间复杂度为O(n²)。
核心思想
1. 选定一个点,这个点满足两个条件:1.未被选过,2.距离最短
2. 对于这个点的所有邻近点去尝试松弛
下面给出在这个赛事系统的迪杰斯特拉的核心算法
public class DijAlo {
public static int MaxValue = 100000;
public static void dijstra(int[][] matrix, int source) {
//最短路径长度
int[] shortest = new int[matrix.length];
//判断该点的最短路径是否求出
int[] visited = new int[matrix.length];
//存储输出路径
String[] path = new String[matrix.length];
//初始化输出路径
for (int i = 0; i < matrix.length; i++) {
path[i] = new String(source + "->" + i);
}
//初始化源节点
shortest[source] = 0;
visited[source] = 1;
for (int i = 1; i < matrix.length; i++) {
int min = Integer.MAX_VALUE;
int index = -1;
for (int j = 0; j < matrix.length; j++) {
//已经求出最短路径的节点不需要再加入计算并判断加入节点后是否存在更短路径
if (visited[j] == 0 && matrix[source][j] < min) {
min = matrix[source][j];
index = j;
}
}
//更新最短路径
shortest[index] = min;
visited[index] = 1;
//更新从index跳到其它节点的较短路径
for (int m = 0; m < matrix.length; m++) {
if (visited[m] == 0 && matrix[source][index] + matrix[index][m] < matrix[source][m]) {
matrix[source][m] = matrix[source][index] + matrix[index][m];
path[m] = path[index] + "->" + m;
}
}
}
//打印最短路径
for (int i = 0; i < matrix.length; i++) {
if (i != source) {
if (shortest[i] == MaxValue) {
System.out.println(source + "到" + i + "不可达");
} else {
System.out.println(source + "到" + i + "的最短路径为:" + path[i] + ",最短距离是:" + shortest[i]);
}
}
}
}
}
以下为代码源码:
package cn.just.eventmanagementsystem.BST;
import cn.just.eventmanagementsystem.Team.Team;
import org.springframework.stereotype.Component;
/**
* 二叉搜索树(Binary Search Tree, BST)类
* 说明:二叉搜索树是一种特殊的二叉树,它的左子树的键值小于根节点的键值,右子树的键值大于根节点的键值
*/
@Component
public class BST {
// 根节点
private BSTNode root;
// 路径长度(查找时经过的节点数)
private int pathLength;
// 节点数
private int numNodes;
/**
* 填充二叉搜索树
*/
public void insert(int teamNumber, Team team){
// 如果根节点为空,则将新节点作为根节点
if (root == null) {
// 创建新节点,并将其作为根节点
root = BSTNode.builder().key(teamNumber).team(team).build();
// 节点数加一
numNodes++;
return;
}
// 如果根节点不为空,则从根节点开始查找要插入的位置
insert(root,teamNumber,team);
}
/**
* 该方法用于向二叉搜索树中插入节点
* @param node 二叉搜索树的根节点
* @param key 键值
* @param team 参赛队伍
*/
private void insert(BSTNode node,int key,Team team) {
// 如果节点的键值大于要插入的键值,则在左子树中插入
if (node.getKey() > key) {
// 如果左子节点为空,则将新节点作为左子节点
if (node.getLeft() == null) {
// 创建新节点,并将其作为左子节点
node.setLeft(BSTNode.builder().key(key).team(team).build());
// 节点数加一
numNodes++;
return;
}
// 如果左子节点不为空,则从左子节点开始查找要插入的位置
insert(node.getLeft(), key, team);
}
// 如果节点的键值小于要插入的键值,则在右子树中插入
if (node.getKey() < key) {
// 如果右子节点为空,则将新节点作为右子节点
if (node.getRight() == null) {
// 创建新节点,并将其作为右子节点
node.setRight(BSTNode.builder().key(key).team(team).build());
// 节点数加一
numNodes++;
return;
}
// 如果右子节点不为空,则从右子节点开始查找要插入的位置
insert(node.getRight(), key, team);
}
}
/**
* 该方法用于向二叉搜索树中插入节点
* @param key 键值
* @return 插入的节点
*/
public BSTNode search(int key){
// 重置路径长度
pathLength = 0;
return search(root,key);
}
/**
* 该方法用于在二叉搜索树中查找键值为 key 的节点
*
* @param node 二叉搜索树的根节点
* @param key 键值
* @return 键值为 key 的节点
*/
private BSTNode search(BSTNode node,int key){
// 路径长度加一
pathLength++;
// 如果节点为空或者节点的键值等于要查找的键值,则返回该节点
if (node == null || node.getKey() == key) {
return node;
}
// 如果节点的键值大于要查找的键值,则在左子树中查找
if (node.getKey() > key) {
return search(node.getLeft(), key);
}
// 如果节点的键值小于要查找的键值,则在右子树中查找
return search(node.getRight(), key);
}
/**
* 获取平均路径长度
* @return 平均路径长度
*/
//获取平均路径长度
public double getAveragePathLength(){
// 计算公式:路径长度 / 节点数
return (double) pathLength / numNodes;
}
}
package cn.just.eventmanagementsystem.BST;
import cn.just.eventmanagementsystem.Team.Team;
import lombok.Builder;
import lombok.Data;
/**
* 二叉搜索树(Binary Search Tree, BST)节点类,其中包含键值和参赛队伍 {@link Team} 数据
*/
@Data
@Builder
public class BSTNode {
// 键值
private int key;
// 参赛队伍
private Team team;
// 左子节点
private BSTNode left;
// 右子节点
private BSTNode right;
}
package cn.just.eventmanagementsystem.CatchMessage;
import cn.just.eventmanagementsystem.Team.Team;
import cn.just.eventmanagementsystem.StringOutput.TypeChange;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
//存储抓取参赛队信息
public class TeamInfo {
// 存放所有参赛队信息的集合
public static List<Team> teamList = new ArrayList<>();
// 在项目启动时加载所有参赛队信息
static{
try(BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("src/main/resources/team.txt"), "GBK"))){
// 读取文件中的所有参赛队信息
String line = null;
while((line = reader.readLine()) != null){
// 去除所有空格
line = line.replaceAll(" ", "");
line = line.trim();
// 从第二行开始读取
if(line.startsWith("参赛队编号")){
continue;
}
// 将每一行的信息存入数组
String[] teamInfo = line.split("#");
// 将每一行的信息存入Team对象
Team team = new Team().builder()
.teamNumber(TypeChange.stringToInt(teamInfo[0])) //转换为整型,后续查找会用到
.projectName(teamInfo[1])
.schoolName(teamInfo[2])
.eventCategory(teamInfo[3])
.participants(teamInfo[4])
.guideTeacher(teamInfo[5])
.build();
// 将 Team 对象存入集合列表
teamList.add(team);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package cn.just.eventmanagementsystem.DijAlo;
public class DijAlo {
//不能设置为Integer.MAX_VALUE,否则两个Integer.MAX_VALUE相加会溢出导致出现负权
public static int MaxValue = 100000;
public static void dijstra(int[][] matrix, int source) {
//最短路径长度
int[] shortest = new int[matrix.length];
//判断该点的最短路径是否求出
int[] visited = new int[matrix.length];
//存储输出路径
String[] path = new String[matrix.length];
//初始化输出路径
for (int i = 0; i < matrix.length; i++) {
path[i] = new String(source + "->" + i);
}
//初始化源节点
shortest[source] = 0;
visited[source] = 1;
for (int i = 1; i < matrix.length; i++) {
int min = Integer.MAX_VALUE;
int index = -1;
for (int j = 0; j < matrix.length; j++) {
//已经求出最短路径的节点不需要再加入计算并判断加入节点后是否存在更短路径
if (visited[j] == 0 && matrix[source][j] < min) {
min = matrix[source][j];
index = j;
}
}
//更新最短路径
shortest[index] = min;
visited[index] = 1;
//更新从index跳到其它节点的较短路径
for (int m = 0; m < matrix.length; m++) {
if (visited[m] == 0 && matrix[source][index] + matrix[index][m] < matrix[source][m]) {
matrix[source][m] = matrix[source][index] + matrix[index][m];
path[m] = path[index] + "->" + m;
}
}
}
//打印最短路径
for (int i = 0; i < matrix.length; i++) {
if (i != source) {
if (shortest[i] == MaxValue) {
System.out.println(source + "到" + i + "不可达");
} else {
System.out.println(source + "到" + i + "的最短路径为:" + path[i] + ",最短距离是:" + shortest[i]);
}
}
}
}
}
package cn.just.eventmanagementsystem.Kind;
/**
* 赛事类别枚举类(保留后续扩展)
*/
public enum EventCategory {
// 未知类型
UNKNOWN,
// 软件应用与开发
SOFTWARE_APPLICATION_AND_DEVELOPMENT,
// 微课与教学辅助
MICRO_COURSE_AND_TEACHING_ASSISTANCE,
// 物联网应用
IOT_APPLICATION,
// 大数据应用
BIG_DATA_APPLICATION,
// 人工智能应用
ARTIFICIAL_INTELLIGENCE_APPLICATION,
// 信息可视化设计
INFORMATION_VISUALIZATION_DESIGN,
// 数媒静态设计
DIGITAL_MEDIA_STATIC_DESIGN,
// 数媒动漫与短片
DIGITAL_MEDIA_ANIMATION_AND_SHORT_FILM,
// 数媒游戏与交互设计
DIGITAL_MEDIA_GAME_AND_INTERACTION_DESIGN,
// 计算机音乐创作
COMPUTER_MUSIC_COMPOSITION,
// 国际生“学汉语,写汉字”
INTERNATIONAL_STUDENTS_LEARN_CHINESE_AND_WRITE_CHINESE_CHARACTERS,
}
package cn.just.eventmanagementsystem.Order;
public class LinkedQueue {
private int front,rear; //声明队头和队尾
private int count; //声明承载记录总人数作用的变量
public static final int MAX = 100;//定义最大值
private final int[] arr = new int[MAX];//确定数组的最大值
private int num;//用于承载队中人数随时变换的数据变量
public LinkedQueue() {//定义无参构造方法
front = 0;
rear = 0;
count = 0;
num=0;
}
public void GetNumber(LinkedQueue a){//用于表达取号的方法
rear = rear % MAX; //取号时便相当于入队,将rear指针做出移动
arr[rear] = count; //向队列中依次放对应人数的排序数字
rear++;
count++;
num++;
if (a.Full()){//如果队满,则不输出相关信息
System.out.println("叫号系统繁忙,请稍后再试");
}else {
System.out.println("队伍" + a.getCount() + "前面还有" + (a.getNum() - 1) + "个队伍在比赛");
}
}
public void CallNumber(LinkedQueue a){ //用于表达叫号的方法
if (isEmpty()) //如果队列中没有元素,即队空情况
System.out.println("现在没有进行比赛");
else { //不是队空情况,那么让头指针先向后移动,再依次输出每次调用叫号方法时头指针的内容
front++;
System.out.println("现在请"+a.getFront()+"号队伍进行比赛");
num--;
}
}
//以下为各个变量的getter和setter
public int getFront() {
return front;
}
public int getNum() {
return num;
}
public int getCount() {
return count;
}
//以下为判断方法
public boolean Full(){ //用于表达判断队满的方法
return rear % MAX == front;
}
public boolean isEmpty() { //用于表达判空的方法
return rear == front;
}
}
package cn.just.eventmanagementsystem.Room;
import cn.just.eventmanagementsystem.Team.Team;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* 决赛叫号室
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class FinalRoom implements Runnable{
// 决赛室
private String roomName;
// 决赛室的队伍
private List<Team> teamList;
@Override
public void run() {
synchronized(this){
System.out.println("决赛室" + roomName + "开始叫号");
for (Team team : teamList) {
System.out.println("决赛室" + roomName + "叫号:" + team.getTeamNumber());
try{
// 每隔0.5秒叫号一次
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("决赛室" + roomName + "叫号结束");
}
}
}
package cn.just.eventmanagementsystem.Room;
import cn.just.eventmanagementsystem.CatchMessage.TeamInfo;
import cn.just.eventmanagementsystem.Service.TeamService;
import cn.just.eventmanagementsystem.Service.TeamServiceImpl;
import cn.just.eventmanagementsystem.Team.Team;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 决赛叫号系统
*/
@Data
public class FinalsCallSystem {
// 决赛室 1
public static List<Team> teamList1 = new ArrayList<>();
private static TeamService teamService = new TeamServiceImpl();
// 静态代码块(为每个决赛室添加对应的参赛队伍)
static {
// 查询所有的游戏设计赛事参赛队伍
List<Team> designTeamList = teamService.getByEventCategory("游戏设计");
// 将游戏设计赛事参赛队伍添加到决赛室 1
teamList1.addAll(designTeamList);
}
}
package cn.just.eventmanagementsystem.Service;
import cn.just.eventmanagementsystem.Team.Team;
import java.util.List;
/**
* 对参赛队进行 CRUD (增删改查)操作
*/
public interface TeamService { //接口
/**
* 新增参赛队伍信息
* @param team 要添加的参赛队伍信息
*/
void addTeamInfo(Team team);
/**
* 根据参赛队伍编号删除参赛队伍信息
* @param teamNumber 要删除的参赛队伍编号
*/
void deleteTeamInfo(Integer teamNumber);
/**
* 根据参赛队伍编号查看参赛队伍信息
* @param team 要修改的参赛队伍信息
*/
void updateTeamInfo(Team team);
/**
* 根据参赛队伍编号查看参赛队伍信息
* @param teamNumber 要查看的参赛队伍编号
*/
void searchTeamByNumber(int teamNumber);
/**
* 根据学校名称查看参赛队伍信息
* @param schoolName 要查看的学校名称
*/
void searchTeamsBySchoolName(String schoolName);
/**
* 根据赛事类别查看参赛队伍信息
* @param eventCategory 要查看的赛事类别
*/
void searchTeamsByEventCategory(String eventCategory);
List<Team> getByEventCategory(String eventCategory);
}
package cn.just.eventmanagementsystem.Service;
import cn.just.eventmanagementsystem.BST.BST;
import cn.just.eventmanagementsystem.BST.BSTNode;
import cn.just.eventmanagementsystem.Team.Team;
import cn.just.eventmanagementsystem.CatchMessage.TeamInfo;
import lombok.Data;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Data
@Service
public class TeamServiceImpl implements TeamService { //实现
/**
* 查看所有参赛队伍信息
*/
public static void showTeamInfo(){
System.out.println("参赛队编号\t#\t参赛作品名称\t#\t参赛学校\t#\t赛事类别\t#\t参赛者\t#\t指导教师");
for (Team team : TeamInfo.teamList) {
System.out.println(team.getTeamNumber()
+ " " + team.getProjectName()
+ " " + team.getSchoolName()
+ " " + team.getEventCategory()
+ " " + team.getParticipants()
+ " " + team.getGuideTeacher());
}
}
/**
* 添加参赛队伍信息
* @param team 要添加的参赛队伍信息
*/
@Override
public void addTeamInfo(Team team){
// 将 Team 对象存入集合
TeamInfo.teamList.add(team);
}
/**
* 根据参赛队伍编号删除参赛队伍信息
* @param teamNumber 要删除的参赛队伍编号
*/
@Override
public void deleteTeamInfo(Integer teamNumber) {
for (Team team : TeamInfo.teamList) {
if (team.getTeamNumber() == teamNumber) {
TeamInfo.teamList.remove(team);
break;
}
}
}
/**
* 修改参赛队伍信息
* @param team 要修改的参赛队伍信息
*/
@Override
public void updateTeamInfo(Team team) {
// 遍历列表查找要修改的参赛队伍信息
for (Team t : TeamInfo.teamList) {
// 根据参赛队伍编号修改参赛队伍信息
if (t.getTeamNumber() == team.getTeamNumber()) {
t.setProjectName(team.getProjectName());
t.setSchoolName(team.getSchoolName());
t.setEventCategory(team.getEventCategory());
t.setParticipants(team.getParticipants());
t.setGuideTeacher(team.getGuideTeacher());
break;
}
}
}
/**
* 根据参赛队伍编号查看参赛队伍信息
* 说明:使用基于二叉排序树的查找算法,若查找成功则返回参赛队伍信息,同时输出查找成功时的平均查找长度 ASL,
* @param teamNumber 要查看的参赛队伍编号
*/
@Override
public void searchTeamByNumber(int teamNumber) {
// 实例化二叉排序树(BST)
BST bst = new BST();
// 填充二叉排序树(BST)
for (Team team : TeamInfo.teamList) {
bst.insert(team.getTeamNumber(), team);
}
// 查找参赛队伍信息
BSTNode resultNode = bst.search(teamNumber);
// 若查找失败则输出 ”查找失败“,否则输出查找成功时的平均查找长度 ASL
if (resultNode == null) {
System.out.println("查找失败");
} else {
// 输出查找到的参赛队伍信息
System.out.println("***********************查询结果***********************");
System.out.println("查找成功,平均查找长度 ASL = " + bst.getAveragePathLength());
System.out.println("参赛队编号\t#\t参赛作品名称\t#\t参赛学校\t#\t赛事类别\t#\t参赛者\t#\t指导教师");
System.out.println(resultNode.getTeam().getTeamNumber()
+ " " + resultNode.getTeam().getProjectName()
+ " " + resultNode.getTeam().getSchoolName()
+ " " + resultNode.getTeam().getEventCategory()
+ " " + resultNode.getTeam().getParticipants()
+ " " + resultNode.getTeam().getGuideTeacher());
}
}
/**
* 根据参赛队伍名称查看参赛队伍信息
* 说明:用归并排序(Merge Sort)来进行赛事类别(eventCategory)的排序,
* 因为归并排序对于大的数据集来说非常高效,时间复杂度为O(n log n),并且它是稳定的排序算法,
* 这意味着相同的元素在排序后会保持原有的顺序。
*
* @param schoolName 要查看的学校名称
*/
@Override
public void searchTeamsBySchoolName(String schoolName) {
// 声名一个新的数组,用于存放查找到的参赛队伍信息
List<Team> schoolTeams = new ArrayList<>();
// 遍历列表查找要查看的参赛队伍信息
for (Team team : TeamInfo.teamList) {
// 如果属于同一个学校,则将其添加到新的数组中
if (team.getSchoolName().trim().equals(schoolName.trim())) {
schoolTeams.add(team);
}
}
// 未找到对应的团队
if (schoolTeams.isEmpty()) {
System.out.println("没有找到对应的团队");
return;
}
// 对 schoolTeams 归并排序
schoolTeams = mergeSort(schoolTeams);
// 输出团队基本信息
System.out.println("********************查询结果*****************");
System.out.println("参赛队编号\t#\t参赛作品名称\t#\t参赛学校\t#\t赛事类别\t#\t参赛者\t#\t指导教师");
for (Team team : schoolTeams) {
System.out.println(team.getTeamNumber()
+ " " + team.getProjectName()
+ " " + team.getSchoolName()
+ " " + team.getEventCategory()
+ " " + team.getParticipants()
+ " " + team.getGuideTeacher());
}
}
/**
* 根据赛事类别查看参赛队伍信息
* @param eventCategory 要查看的赛事类别
*/
@Override
public void searchTeamsByEventCategory(String eventCategory) {
// 声名一个新的数组,用于存放查找到的参赛队伍信息
List<Team> eventCategoryTeams = new ArrayList<>();
// 遍历列表查找要查看的参赛队伍信息
for (Team team : TeamInfo.teamList) {
// 如果属于同一个学校,则将其添加到新的数组中
if(team.getEventCategory().trim().equals(eventCategory.trim())) {
eventCategoryTeams.add(team);
}
}
// 未找到对应的团队
if (eventCategoryTeams.isEmpty()) {
System.out.println("没有找到对应的团队");
return;
}
// 对 schoolTeams 归并排序
eventCategoryTeams = mergeSort(eventCategoryTeams);
// 输出团队基本信息
System.out.println("********************查询结果*****************");
System.out.println("参赛队编号\t#\t参赛作品名称\t#\t参赛学校\t#\t赛事类别\t#\t参赛者\t#\t指导教师");
for (Team team : eventCategoryTeams) {
System.out.println(team.getTeamNumber()
+ " " + team.getProjectName()
+ " " + team.getSchoolName()
+ " " + team.getEventCategory()
+ " " + team.getParticipants()
+ " " + team.getGuideTeacher());
}
}
@Override
public List<Team> getByEventCategory(String eventCategory) {
return null;
}
/**
* 归并排序
* @param teams 要排序的参赛队伍信息
* @return 排序后的参赛队伍信息
*/
private static List<Team> mergeSort(List<Team> teams) {
// 如果列表为空或者只有一个元素,则直接返回
if (teams.size() < 2) {
return teams;
}
// 将列表分为两部分
int midIndex = teams.size() / 2;
// 左边的列表
List<Team> left = new ArrayList<>(teams.subList(0, midIndex));
// 右边的列表
List<Team> right = new ArrayList<>(teams.subList(midIndex, teams.size()));
// 调用递归函数,分别对左右两边的列表进行排序
return merge(mergeSort(left), mergeSort(right));
}
/**
* 合并两个有序列表
* @param left 左边的列表
* @param right 右边的列表
* @return 合并后的列表
*/
private static List<Team> merge(List<Team> left, List<Team> right) {
// 合并后的列表
List<Team> merged = new ArrayList<>();
// 初始化左右两个列表的索引
int leftIndex = 0, rightIndex = 0;
// 循环比较两个列表的元素
while (leftIndex < left.size() && rightIndex < right.size()) {
// 如果左边的元素小于等于右边的元素,则将左边的元素添加到合并后的列表中
if (left.get(leftIndex).getEventCategory().compareTo(right.get(rightIndex).getEventCategory()) <= 0) {
merged.add(left.get(leftIndex++));
} else {
// 否则将右边的元素添加到合并后的列表中
merged.add(right.get(rightIndex++));
}
}
// 将剩余的元素添加到合并后的列表中
while (leftIndex < left.size()) {
merged.add(left.get(leftIndex++));
}
// 将剩余的元素添加到合并后的列表中
while (rightIndex < right.size()) {
merged.add(right.get(rightIndex++));
}
// 返回合并后的列表
return merged;
}
}
package cn.just.eventmanagementsystem.StringOutput;
//字符转换
public class TypeChange {
//将字符串转化为整形,对参赛编号的查找会用到
public static int stringToInt(String str) {
// 除去字符串中的空格
str = str.trim();
return Integer.parseInt(str);
}
}
package cn.just.eventmanagementsystem.Team;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// 参赛队伍类别
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class Team {
// 参赛队伍编号
private int teamNumber;
// 项目名称
private String projectName;
// 学校名称
private String schoolName;
// 赛事类别
private String eventCategory;
// 参赛队员
private String participants;
// 指导老师
private String guideTeacher;
}
package cn.just.eventmanagementsystem;
import cn.just.eventmanagementsystem.Team.Team;
import cn.just.eventmanagementsystem.CatchMessage.TeamInfo;
import cn.just.eventmanagementsystem.Service.TeamService;
import cn.just.eventmanagementsystem.Service.TeamServiceImpl;
import cn.just.eventmanagementsystem.StringOutput.TypeChange;
import cn.just.eventmanagementsystem.Room.FinalRoom;
import cn.just.eventmanagementsystem.Room.FinalsCallSystem;
import java.util.Scanner;
import static cn.just.eventmanagementsystem.DijAlo.DijAlo.dijstra;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.println("欢迎来到赛事管理系统,请根据提示完成您所需的操作");
System.out.println("0.退出系统");
System.out.println("1.对参赛队伍信息进行查看");
System.out.println("2.对参赛队伍信息进行增加");
System.out.println("3.对参赛队伍信息进行修改");
System.out.println("4.对参赛队伍信息进行删除");
System.out.println("5.根据编号进行查找,并计算ASL");
System.out.println("6.根据学校名称进行查找");
System.out.println("7.根据赛事类别进行查找");
System.out.println("8.使用导航功能");
System.out.println("9.使用赛事叫号系统");
int choice = scanner.nextInt();
switch (choice) {
case 1:
TeamServiceImpl.showTeamInfo();
break;
case 2: {
System.out.println("请输入参赛队伍信息(参赛队编号#参赛作品名称#参赛学校#赛事类别#参赛者#指导教师):");
String input = scanner.next();
String[] teams = input.split("#");
Team team = new Team();
for (int i = 0; i < teams.length; i++) {
team.setTeamNumber(TypeChange.stringToInt(teams[0]));
team.setProjectName(teams[1]);
team.setSchoolName(teams[2]);
team.setEventCategory(teams[3]);
team.setParticipants(teams[4]);
team.setGuideTeacher(teams[5]);
}
TeamInfo.teamList.add(team);
break;
}
case 3: {
System.out.println("请输入要修改的参赛队伍编号:");
int teamNumber = scanner.nextInt();
System.out.println("请输入修改后的参赛队伍信息(参赛队编号#参赛作品名称#参赛学校#赛事类别#参赛者#指导教师):");
String input = scanner.next();
String[] teams = input.split("#");
Team team = new Team();
for (int i = 0; i < teams.length; i++) {
team.setTeamNumber(TypeChange.stringToInt(teams[0]));
team.setProjectName(teams[1]);
team.setSchoolName(teams[2]);
team.setEventCategory(teams[3]);
team.setParticipants(teams[4]);
team.setGuideTeacher(teams[5]);
}
for (int i = 0; i < TeamInfo.teamList.size(); i++) {
if (TeamInfo.teamList.get(i).getTeamNumber() == teamNumber) {
TeamInfo.teamList.set(i, team);
}
}
break;
}
case 4: {
System.out.println("请输入要删除的参赛队伍编号:");
int teamNumber = scanner.nextInt();
for (int i = 0; i < TeamInfo.teamList.size(); i++) {
if (TeamInfo.teamList.get(i).getTeamNumber() == teamNumber) {
TeamInfo.teamList.remove(i);
}
}
break;
}
case 5: {
System.out.println("请输入要查找的参赛队伍编号:");
String teamNumber = scanner.next();
int number = TypeChange.stringToInt(teamNumber);
TeamService teamService = new TeamServiceImpl();
teamService.searchTeamByNumber(number);
}
case 6: {
System.out.println("请输入要查找的参赛队伍学校名称:");
String schoolName = scanner.next();
TeamService teamService = new TeamServiceImpl();
teamService.searchTeamsBySchoolName(schoolName);
}
case 7: {
System.out.println("请输入要查找的参赛队伍赛事类别:");
String eventCategory = scanner.next();
TeamService teamService = new TeamServiceImpl();
teamService.searchTeamsByEventCategory(eventCategory);
}
case 8:{
int N = 10000;
int MaxValue = 100000;
Scanner input = new Scanner(System.in);
System.out.println("0:7号组团"+'\n'+"1:南门"+'\n'+"2:明德楼"+'\n'+"3:文理大楼"+'\n'+"4:计算机学院楼"+'\n'+
"5:大学生活动中心"+'\n'+"6:图书馆"+'\n'+"7:生物技术学院"+'\n'+"8:材料学院"+'\n'+"9:后勤服务楼");
System.out.println("请输入您的所在地,我们将为您规划去各地的最短路线");
char[] vertexes = { 'A', 'B', 'C', 'D', 'E', 'F', 'G' ,'H','I','J'};
//初始化邻接矩阵,将各地之间的距离信息内容填入
int[][] matrix = { // 图的邻接矩阵
/*A*//*B*//*C*//*D*//*E*//*F*//*G*//*H*//*I*//*J*/
/*A*/{0, N, 3, N, N, N, N, N, N, 2 },
/*B*/{N, 0, N, N, N, 2, N, N, N, 2 },
/*C*/{3, N, 0, 2, N, N, N, N, 4, 3 },
/*D*/{N, N, 2, 0, 1, N, N, 3, N, N },
/*E*/{N, N, N, 1, 0, N, 2, N, N, N },
/*F*/{2, N, N, N, N, 0, N, N, 2, 3 },
/*G*/{N, N, N, N, 2, N, 0, 3, N, N },
/*H*/{N, N, N, 3, N, N, 3, 0, 2, N },
/*I*/{N, N, 4, N, N, 2, N, 2, 0, N },
/*J*/{2, 2, 3, N, N, 3, N, N, N, 0 }
};
//单源最短路径,源点
int source = input.nextInt();
//调用dijstra算法计算最短路径
dijstra(matrix, source);
break;
}
case 9: {
// 创建每个决赛室的线程
Thread roomThread1 = new Thread(new FinalRoom("决赛室1", FinalsCallSystem.teamList1));
// 启动线程
System.out.println("决赛开始!");
roomThread1.start();
try {
// 等待线程结束
roomThread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("决赛结束!");
}
case 0:
System.exit(0);
}
}
}
}