课设预习报告

数据结构课程设计预习报告

1.问题描述

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

1.能够管理各参赛队的基本信息

包含参赛队编号,参赛作品名称,参赛学校,赛事类别,参赛者,指导老师),赛事类别共11项,包括增加、删除、修改参赛队伍的信息。

 1 public class Team {
 2     private int teamId; // 参赛队编号
 3     private String teamName; // 参赛作品名称
 4     private String school; // 参赛学校
 5     private String eventType; // 赛事类别
 6     private String participant; // 参赛者
 7     private String teacher; // 指导老师
 8 
 9     public Team(int teamId, String teamName, String school, String eventType, String participant, String teacher) {
10         this.teamId = teamId;
11         this.teamName = teamName;
12         this.school = school;
13         this.eventType = eventType;
14         this.participant = participant;
15         this.teacher = teacher;
16     }
17 
18     public int getTeamId() {
19         return teamId;
20     }
21 
22     public String getTeamName() {
23         return teamName;
24     }
25 
26     public String getSchool() {
27         return school;
28     }
29 
30     public String getEventType() {
31         return eventType;
32     }
33 
34     public String getParticipant() {
35         return participant;
36     }
37 
38     public String getTeacher() {
39         return teacher;
40     }
41 
42     @Override
43     public String toString() {
44         return "参赛队伍信息:" +
45                 "参赛队编号:" + teamId +
46                 ", 参赛作品名称:" + teamName +
47                 ", 参赛学校:" + school +
48                 ", 赛事类别:" + eventType +
49                 ", 参赛者:" + participant +
50                 ", 指导老师:" + teacher;
51     }
52 }

 

2.从team.txt中读取参赛队伍的基本信息,实现基于二叉排序树的查找。

根据提示输入参赛队编号,若查找成功,输出该赛事类别对应的基本信息(参赛作品名称、参赛学校、赛事类别、参赛者和指导老师信息),同时,输出查找成功时的平均查找长度ASL;否则,输出“查找失败!”。

// 从team.txt中读取参赛队伍信息

 1  public void readTeamFile(String filename) {
 2         File file = new File(filename);
 3         try {
 4             BufferedReader reader = new BufferedReader(new FileReader(file));
 5             String line = null;
 6             while ((line = reader.readLine()) != null) { // 读取文件内容
 7                 String[] data = line.split("#"); // 按符号“#”切分数据
 8                 int teamId = Integer.parseInt(data[0]);
 9                 String teamName = data[1];
10                 String school = data[2];
11                 String eventType = data[3];
12                 String participant = data[4];
13                 String teacher = data[5];
14                 Team team = new Team(teamId, teamName, school, eventType, participant, teacher);
15                 addTeam(team);
16             }
17         } catch (IOException e) {
18             e.printStackTrace();
19         }
20     }

 

 

// 基于二叉排序树的查找

 1 public void search() {
 2         Scanner scanner = new Scanner(System.in);
 3         System.out.println("请输入要查找的参赛队编号:");
 4         int teamId = scanner.nextInt();
 5         BinarySortTree.BSTNode temp = binarySortTree.search(teamId);
 6         if (temp != null) { // 查找成功
 7             Team team = (Team) temp.getData();
 8             System.out.println(team);
 9             System.out.println("平均查找长度ASL:" + binarySortTree.getASL());
10         } else { // 查找失败
11             System.out.println("查找失败!");
12         }
13     }

 

//二叉树类

 

public class BinarySortTree {
    private BSTNode root;
    private int size;
    private int sum; //二叉排序树中所有结点的深度之和

    public BinarySortTree() {
        root = null;
        size = 0;
        sum = 0;
    }

    public BSTNode getRoot() {
        return root;
    }

    public int getSize() {
        return size;
    }

    public int getASL() {
        return sum / size;
    }

    // 插入操作
    public void insert(int key, Object data) {
        insert(root, key, data);
    }

    private void insert(BSTNode node, int key, Object data) {
        if (root == null) {
            root = new BSTNode(key, data);
            size++;
            return;
        }
        if (node == null) {
            node = new BSTNode(key, data);
            size++;
            return;
        }
        if (key < node.key) {
            if (node.leftChild == null) {
                node.leftChild = new BSTNode(key, data);
                size++;
                return;
            }
            insert(node.leftChild, key, data);
        } else if (key > node.key) {
            if (node.rightChild == null) {
                node.rightChild = new BSTNode(key, data);
                size++;
                return;
            }
            insert(node.rightChild, key, data);
        } else {
            node.data = data;
        }
    }

    // 删除操作
    public boolean delete(int key) {
        BSTNode parent = root; // 记录要删除结点的父结点
        BSTNode current = root; // 记录要删除结点
        boolean isLeftChild = true;
        while (current.key != key) {
            parent = current;
            if (key < current.key) {
                isLeftChild = true;
                current = current.leftChild;
            } else {
                isLeftChild = false;
                current = current.rightChild;
            }
            if (current == null) {
                return false;
            }
        }
        // 情况1:要删除的结点没有子结点
        if (current.leftChild == null && current.rightChild == null) {
            if (current == root) {
                root = null;
            } else if (isLeftChild) {
                parent.leftChild = null;
            } else {
                parent.rightChild = null;
            }
        }
        // 情况2:要删除的结点只有一个子结点
        else if (current.rightChild == null) {
            if (current == root) {
                root = current.leftChild;
            } else if (isLeftChild) {
                parent.leftChild = current.leftChild;
            } else {
                parent.rightChild = current.leftChild;
            }
        } else if (current.leftChild == null) {
            if (current == root) {
                root = current.rightChild;
            } else if (isLeftChild) {
                parent.leftChild = current.rightChild;
            } else {
                parent.rightChild = current.rightChild;
            }
        }
        // 情况3:要删除的结点有两个子结点
        else {
            BSTNode successor = getSuccessor(current);
            if (current == root) {
                root = successor;
            } else if (isLeftChild) {
                parent.leftChild = successor;
            } else {
                parent.rightChild = successor;
            }
            successor.leftChild = current.leftChild;
        }
        size--;
        return true;
    }

    // 获取后继结点
    private BSTNode getSuccessor(BSTNode delNode) {
        BSTNode successorParent = delNode;
        BSTNode successor = delNode;
        BSTNode current = delNode.rightChild;
        while (current != null) {
            successorParent = successor;
            successor = current;
            current = current.leftChild;
        }
        if (successor != delNode.rightChild) {
            successorParent.leftChild = successor.rightChild;
            successor.rightChild = delNode.rightChild;
        }
        return successor;
    }

    // 修改操作
    public void update(int key, Object newData) {
        BSTNode node = search(key);
        if (node != null) {
            node.data = newData;
        }
    }

    // 查找操作
    public BSTNode search(int key) {
        BSTNode current = root;
        while (current != null && current.key != key) {
            if (key < current.key) {
                current = current.leftChild;
            } else {
                current = current.rightChild;
            }
        }
        return current;
    }

    // 中序遍历操作
    public void inorderTraversal(BSTNode node, Queue queue, int eventType) {
        if (node != null) {
            inorderTraversal(node.leftChild, queue, eventType);
            Team team = (Team) node.data;
            if (team.getEventType().equals(String.valueOf(eventType))) { // 赛事类别匹配
                queue.enqueue(team);
            }
            sum += getNodeDepth(node);
            inorderTraversal(node.rightChild, queue, eventType);
        }
    }

    // 计算结点深度
    private int getNodeDepth(BSTNode node) {
        if (node == null || node == root) {
            return 0;
        }
        int depth = 1;
        BSTNode parent = node.parent;
        while (parent != null) {
            depth++;
            parent = parent.parent;
        }
        return depth;
    }

    // 二叉排序树结点类
    public class BSTNode {
        private int key;
        private Object data;
        private BSTNode parent;
        private BSTNode leftChild;
        private BSTNode rightChild;

        public BSTNode(int key, Object data) {
            this.key = key;
            this.data = data;
            parent = leftChild = rightChild = null;
        }

        public int getKey() {
            return key;
        }

        public Object getData() {
            return data;
        }

        public BSTNode getParent() {
            return parent;
        }

        public BSTNode getLeftChild() {
            return leftChild;
        }

        public BSTNode getRightChild() {
            return rightChild;
        }
    }
}

 

(3)能够提供按参赛学校查询参赛团队(或根据赛事类别查询参赛团队)

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

public void searchByKeyword(String filename){
        try {
            BufferedReader reader = new BufferedReader(new FileReader(filename));
            String line;
            int count = 0;
            List<TEAM> teamList = new ArrayList<TEAM>();//全部队伍列表
            while ((line = reader.readLine()) != null) {
                if (count>0) {
                    String[] fields = line.split("\t#\t");
                    TEAM team = new TEAM(fields[0], fields[1], fields[2],fields[3],fields[4],fields[5]);
                    teamList.add(team);//添加队伍到队伍列表
                }
                count++;
            }
            reader.close();
            Collections.sort(teamList); // 按赛事类别排序(归并排序+快速排序)

            System.out.println("请输入关键字:(参赛学校、赛事类别)");
            Scanner sc = new Scanner(System.in);
            String key = sc.next();
            System.out.println("查找结果:");
            boolean found = false;
            for (TEAM team : teamList){
                if (team.containsKeyword(key)){
                    System.out.println(team);
                    found = true;
                }
            }
            if (!found) System.out.println("未找到相关队伍");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    //内部队伍类
    class TEAM implements Comparable<TEAM>{
        String teamId; // 参赛队编号
        String teamName; // 参赛作品名称
        String school; // 参赛学校
        String eventType; // 赛事类别
        String participant; // 参赛者
        String teacher; // 指导老师

        public TEAM(String teamId, String teamName, String school, String eventType, String participant, String teacher) {
            this.teamId = teamId;
            this.teamName = teamName;
            this.school = school;
            this.eventType = eventType;
            this.participant = participant;
            this.teacher = teacher;
        }

        public boolean containsKeyword(String keyword) {
            return school.contains(keyword) || eventType.contains(keyword);
        }

        @Override
        public String toString() {
            return
                    teamId +'\t'+
                            teamName +'\t'+
                            school +'\t'+
                            eventType +'\t'+
                            participant +'\t'+
                            teacher;
        }

        @Override
        public int compareTo(TEAM o) {
            return this.eventType.compareTo(o.eventType);
        }
    }

 

(4)为省赛现场设计一个决赛叫号系统

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

// 模拟决赛叫号系统
    public void competitionCall(String filename){
        try {
            BufferedReader reader = new BufferedReader(new FileReader(filename));
            String line;
            int count = 0;
            List<Team> teams = new ArrayList<Team>();//全部队伍列表
            while ((line = reader.readLine()) != null) {
                if (count>0) {
                    String[] fields = line.split("\t#\t");
                    Team team = new Team(fields[0], fields[1], fields[2],fields[3],fields[4],fields[5]);
                    teams.add(team);
                }
                count++;
            }
            reader.close();

            //动态分类赛事类别
            Map<String, List<Team>> typeMap = new HashMap<String, List<Team>>();//赛事类型集合
            for (Team team : teams) {
                String type = team.getEventType();
                if (!typeMap.containsKey(type)) {//若不包含该赛事类型
                    List<Team> typeTeams = new ArrayList<Team>();//创建新决赛室
                    typeTeams.add(team);//将队伍添加进决赛室
                    typeMap.put(type, typeTeams);//添加决赛室进赛事类型集合
                } else {
                    typeMap.get(type).add(team);//直接将队伍添加到对应赛事类型的决赛室
                }
            }

            System.out.println("根据赛事类型分决赛室后:");
            int num = 1;
            for (Map.Entry<String, List<Team>> entry : typeMap.entrySet()) {

                System.out.println('\n'+entry.getKey() + ":");
                for (Team team : entry.getValue()) {
                    System.out.println("决赛室" + num + "叫号: " + team.getTeamId()+team.getTeamName());

                }
                num++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

(5)赛事系统为参赛者提供赛地的校园导游程序,为参赛者提供各种路径导航的查询服务。

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

public class CampusNavigator {
    private Map<String, Map<String, Integer>> graph; //图的邻接表表示
    private Map<String, Integer> distances; //起点到各点的最短距离
    private Map<String, String> previousNodes; //最短路径上各个节点的前驱节点
    private Set visitedNodes; //已经完成最短路径搜索的节点集合
    private static int ClosestDistance;//起点与终点间的最短距离

    public CampusNavigator() {
        graph = new HashMap<String, Map<String, Integer>>();
        distances = new HashMap<String, Integer>();
        previousNodes = new HashMap<String, String>();
        visitedNodes = new HashSet<String>();
    }

    //向图中添加一条边
    public void addEdge(String from, String to, int distance) {
        if (!graph.containsKey(from)) {
            graph.put(from, new HashMap<String, Integer>());
        }
        graph.get(from).put(to, distance);
    }

    //查询起点到终点的最短路径
    public List<String> shortestPath(String start, String end) {
        distances.clear();
        previousNodes.clear();
        visitedNodes.clear();
        distances.put(start, 0); //起点到自己的距离为0

        while (!visitedNodes.contains(end)) {
            String currentNode = getClosestUnvisitedNode(); //获取未访问节点中距离起点最近的节点
            visitedNodes.add(currentNode);

            if (!graph.containsKey(currentNode)) { //如果当前节点没有出边,则跳过
                continue;
            }

            //遍历当前节点的所有邻居节点
            for (Map.Entry<String, Integer> neighborEntry : graph.get(currentNode).entrySet()) {
                String neighborNode = neighborEntry.getKey();
                int distanceFromStartToNeighbor = distances.get(currentNode) + neighborEntry.getValue();

                if (!distances.containsKey(neighborNode)
                    || distanceFromStartToNeighbor < distances.get(neighborNode)) {

                    //如果从起点到邻居节点的距离更短,更新距离和前驱节点信息
                    distances.put(neighborNode, distanceFromStartToNeighbor);
                    previousNodes.put(neighborNode, currentNode);
                }
            }
        }
        //根据前驱节点信息构造最短路径
        return getSPath(start, end);
    }

    //获取未访问节点中距离起点最近的节点
    private String getClosestUnvisitedNode() {
        String closestNode = null;// 定义最近距离的节点
        int closestDistance = Integer.MAX_VALUE;// 定义最近距离的初始值为整型最大值
        for (Map.Entry<String, Integer> entry : distances.entrySet()) {// 遍历所有节点到起点的距离
            String node = entry.getKey();
            int distance = entry.getValue();
            if (!visitedNodes.contains(node) && distance < closestDistance) {// 如果节点未被访问过且距离更近
                closestNode = node; // 更新最近距离节点
                closestDistance = distance; // 更新最近距离
            }
        }
        ClosestDistance = closestDistance;//赋值最短距离
        return closestNode; // 返回最近距离的节点
    }

    //根据前驱节点信息构造最短路径
    private List<String> getSPath(String start, String end) {
        List<String> path = new ArrayList<String>();
        for (String node = end; node != null; node = previousNodes.get(node)) {
            path.add(node);
        }
        Collections.reverse(path);
        if (path.get(0) != start) { //起点和终点不连通,返回空路径
            path.clear();
        }
        return path;
    }

    public static void IMpCampusNavigator() {
        CampusNavigator navigator = new CampusNavigator();
        navigator.addEdge("49#宿舍楼", "西食堂", 100);
        navigator.addEdge("49#宿舍楼", "文体中心", 200);
        navigator.addEdge("西食堂", "文体中心", 150);
        navigator.addEdge("西食堂", "明德园", 80);
        navigator.addEdge("文体中心", "西操场", 50);
        navigator.addEdge("明德园", "西操场", 120);
        navigator.addEdge("明德园", "文理大楼", 110);
        navigator.addEdge("西操场", "求学园", 150);
        navigator.addEdge("西操场", "东食堂", 230);
        navigator.addEdge("文理大楼", "海韵湖北", 80);
        navigator.addEdge("文理大楼", "求学园", 60);
        navigator.addEdge("求学园", "图书馆", 70);
        navigator.addEdge("求学园", "东食堂", 90);
        navigator.addEdge("东食堂", "图书馆", 50);
        navigator.addEdge("图书馆", "海韵湖北", 100);

        Scanner sc = new Scanner(System.in);
        String start,end;
        System.out.println("***********欢迎使用江科大简易导航系统***********");
        System.out.println("注意:本系统暂时只录进了以下的地点信息:\n\t49#宿舍楼,西食堂,明德楼,文体中心,西操场,文理大楼,求学园,图书馆,东食堂,海韵湖北");
        System.out.println("请输入起点:");
        start = sc.next();
        System.out.println("请输入终点:");
        end = sc.next();
        List<String> path = navigator.shortestPath(start, end);
        if (path.isEmpty()) {
            System.out.println("起点和终点不连通");
        } else {
            System.out.print("最短路径:");
            for (String node : path) {
                System.out.print(node + " -> ");
            }
            System.out.println("最短距离:"+ClosestDistance);
        }
    }
}

 

2.设计要求

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

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

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

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

posted @ 2023-05-23 11:05  奇蛮  阅读(61)  评论(0)    收藏  举报