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

第一模块的预习报告

——管理各队伍的参赛信息(增、删、改)

1.问题定义

        从txt中读取数据

2.问题分析

        此问题分为几个问题:

                1.如何从txt文件中读取且读取对数据?

                2.读取完数据用什么结构储存?

                3.储存完毕后如何实现增、删、改的功能?

        对于第一个问题,我编写了一个java类,名为FileParser,它实现了从txt文件中读取数据的功能;这里我出现了一个问题:读取后,文件中的数字和符号没问题,但是中文无法正常显示,为乱码。我的解决方案是在读取时用GBK方式读取,很好地解决了这个问题。

        对于第二个问题,我选择了List。原因有几个:1.List是常用的存储数据的结构,自带函数多,功能完善,使用方便,便于数据的存储和增删改查等操作,也易于检测检查。选定List后,我将它并入了类FileParser中。

        对于第三个问题,我主要使用List自带的几个函数,如.add(),.get(),.remove(),.size(),较好地解决了这个问题。

        此外,由于我对java不熟悉,在键入选择时遇到了问题,在查找资料后,我选择了Scanner来键入并选择。

3.概要设计

        主要代码如下:

        FileParser.java:

package org.example;

import java.io.*;
import java.util.ArrayList;
import java.util.List;


public class FileParser {
    private File file;

    private BufferedReader reader;

    private InputStream is;

    private InputStreamReader isReader;

    public FileParser() {}

    public FileParser(String filePath) {
        file = new File(filePath);

        initReader();

    }

    /**

     初始化文件输入32313133353236313431303231363533e78988e69d8331333337613235流,为文件读取做准备

     */

    private void initReader() {
        if(file != null && file.isFile() && file.canRead()) {
//文件存在可读取并且是“文件”而不是目录

            try {
                is = new FileInputStream(file);//创建文件输入流

                isReader = new InputStreamReader(
                        new FileInputStream(file), "GBK");//创建输出流的Reader

                reader = new BufferedReader(isReader);//用于按行读取文件

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

            }

        }

    }

    /**

     转换文件内容,将文件中的数据转换成List

     */

    public List parse() {
        List lstNumber = null;//最终结果保存在这里

        String txtLine = null;//临时变量,保存按行读取到的字符串


//开始读取文件

        if(reader != null) {
            lstNumber = new ArrayList();//初始化List

            try {
                while((txtLine = reader.readLine()) != null) {//按行读取文件

                    lstNumber.add(txtLine);

                }

            } catch (IOException e) {
                e.printStackTrace();

            } finally {
//关闭流

                try {
                    reader.close();

                    isReader.close();

                    is.close();

                } catch (IOException e) {
                    e.printStackTrace();

                }

            }

        }

        return lstNumber;//返回结果

    }

}

        以下是Main.java中的相应代码:

package org.example;
import java.util.ArrayList;
import java.util.List;

import java.util.*;
import java.util.stream.Collectors;

public class Main {

    public static String[][] trans(List List01){
        String[][] sign = new String[List01.size()][6];

        for(int i = 0; i<List01.size();i++)
        {
            String m = String.valueOf(List01.get(i).toString());
            String[] n = m.split("#");
            for(int j = 0; j<6;j++)
            {
                sign[i][j] = n[j];
            }
        }

        return sign;
    }

    public static void main(String[] args) {
        String filePath = "C:\\Users\\花如昼\\Desktop\\数据结构课设相关文件\\team(1).txt";
        FileParser fileParser = new FileParser(filePath);

        List List01 = fileParser.parse();

        String[][] sign;

        sign = trans(List01);

        for(int i = 1; i < List01.size();i++)
        {
            System.out.println("第" + i + "队:");
            for(int j = 0; j<6;j++)
            {
                System.out.println(sign[0][j] + ":" + sign[i][j]);
            }
            System.out.println('\n');
        }

        //二叉排序树的创建
        int[] array = new int[500];

        for (int i = 1;i < List01.size();i++) {
            array[i - 1] = Integer.parseInt(sign[i][0]);
        }

        Node tree = new Node(array[0]);
        for (int i = 0;i < array.length;i++) {
            tree.addNode(new Node(array[i]));
        }


        //开始选择
        System.out.println("请选择操作:1.增加 2.删除 3.修改 4.查找 5.按赛事类别查找 6.按参赛学校查找 7.决赛叫号系统 8.校园导游程序");
        Scanner scanner1 = new Scanner(System.in);
        String x = scanner1.next();

        if(x.equals("1")){
            System.out.println("请按照顺序依次键入想要增加的条目:");
            Scanner scanner2 = new Scanner(System.in);
            String y1 = scanner2.next();
            List01.add(y1);
            System.out.println("增加成功!增加的条目为:");
            String l = List01.get((List01.size()-1)).toString();
            System.out.println(l);

            System.out.println("是否输出增加后的表?1.是 2.否");
            Scanner z1 = new Scanner(System.in);
            int z2 = z1.nextInt();
            if(z2 == 1){
                String[][] sign2;

                sign2 = trans(List01);

                for(int i = 1; i < List01.size();i++)
                {
                    System.out.println("第" + i + "队:");
                    for(int j = 0; j<6;j++)
                    {
                        System.out.println(sign2[0][j] + ":" + sign2[i][j]);
                    }
                    System.out.println('\n');
                }
            }
        }

        if(x.equals("2")){
            System.out.println("若您知道想要删除的信息的位置,请按1;若不知道,请按2,并键入相关信息,系统会返回它的位置同时删除!");
            Scanner scanner3 = new Scanner(System.in);
            int y2 = scanner3.nextInt();
            if(y2 == 1){
                System.out.println("请输入要删除的位置(即第几组):");
                Scanner pos = new Scanner(System.in);
                int k1 = pos.nextInt();
                List01.remove(k1);
            }
            if(y2 == 2){
                System.out.println("请输入相关信息:");
                Scanner massa = new Scanner(System.in);
                String k2 = massa.next();
                int pos = 0;
                for(int i = 1; i < List01.size(); i++){
                    for(int j = 0; j < 6; j++){
                        if(Objects.equals(sign[i][j], k2)){
                            pos = i;
                            break;
                        }
                    }
                }
                System.out.println("找到!位置为:第" + pos + "组,此条目为:" + '\n');
                for(int i = 0; i < 6; i++){
                    System.out.println(sign[0][i] + ":" + sign[pos][i]);
                }
                List01.remove(pos);
                System.out.println('\n' + "已删除!" + '\n');
            }

            System.out.println("是否输出删除后的表?1.是 2.否");
            String[][] sign3;
            sign3 = trans(List01);
            Scanner z1 = new Scanner(System.in);
            int z2 = z1.nextInt();
            if(z2 == 1){
                for(int i = 1; i < List01.size();i++)
                {
                    System.out.println("第" + i + "队:");
                    for(int j = 0; j<6;j++)
                    {
                        System.out.println(sign3[0][j] + ":" + sign3[i][j]);
                    }
                    System.out.println('\n');
                }
            }
        }

        if(x.equals("3")){
            System.out.println("请按顺序依次键入想要修改的位置(第几组)和修改后的内容(以#号隔开):");
            Scanner scanner4 = new Scanner(System.in);
            int y1 = scanner4.nextInt();
            Scanner scanner5 = new Scanner(System.in);
            String y2 = scanner5.next();
            List01.set(y1, y2);

            System.out.println("是否输出修改后的表?1.是 2.否");
            String[][] sign4;
            sign4 = trans(List01);
            Scanner z1 = new Scanner(System.in);
            int z2 = z1.nextInt();
            if(z2 == 1){
                for(int i = 1; i < List01.size();i++)
                {
                    System.out.println("第" + i + "队:");
                    for(int j = 0; j<6;j++)
                    {
                        System.out.println(sign4[0][j] + ":" + sign4[i][j]);
                    }
                    System.out.println('\n');
                }
            }
        }
}

第二模块的预习报告

——实现基于二叉树的查找

1.问题定义

        二叉树的创建、基于二叉树的查找与ASL的计算

2.问题分析

        此模块分为几个问题:

                1、如何创建二叉树?

                2、如何实现查找功能?

                3、如何在查找到相应的编号后找到对应的队伍信息并输出?

                4、ASL的计算?

        第一个问题和第二个问题,我创建了一个java类,用来实现创建和查找。我只把每个队伍的编号放入二叉树,然后进行查找。至于第三个问题,我选择获取编号后,用编号在第一个模块进行查找,然后通过第一个模块中的二维String数组来进行定位和输出。其实此处我的二叉树是单纯用来确定有无这个队伍编号的,仅用来验证是否存在。

        我二叉树的类会放在概要设计中。

        至于第四个问题,就是套公式:总权值(每层结点数×当前层数)/总结点数。这里我用来求总权值的函数运用了一个递归,函数体比较简单,只有几行,但是非常简练和高效。我摘出来贴在下面:

public int BSTasl(int d)//总权值,注意调用时d赋值为0
    {
        d++;
        int a = d;
        if (this.leftNode != null)
            d += this.leftNode.BSTasl(a);
        if (this.rightNode != null)
            d += this.rightNode.BSTasl(a);
        return d;
    }

 3.概要设计

        关于二叉树的java类:

        Node.java:

package org.example;

public class Node {

    private Node leftNode;
    private Node rightNode;
    private int value;

    public Node(int value) {
        super();
        this.value = value;
    }

    public int getValue(){
        return this.value;
    }
    public Node getLeftNode() {
        return leftNode;
    }
    public void setLeftNode(Node leftNode) {
        this.leftNode = leftNode;
    }
    public Node getRightNode() {
        return rightNode;
    }
    public void setRightNode(Node rightNode) {
        this.rightNode = rightNode;
    }

    //添加节点方法
    public void addNode(Node node) {
        if (node == null) {
            System.out.println("该节点为空,不进行添加");
            return;
        }

        //判断传入节点的值是否比当前节点的值小
        if (node.value < value) {

            //如果当前节点的左子节点为空,那么就把传入的节点作为当前节点的左子节点
            if (leftNode == null) {
                leftNode = node;

                //递归遍历当前节点的左子树添加 node
            } else {
                leftNode.addNode(node);
            }

            //否则添加的节点的值大于等于当前节点的值
        } else {

            //如果当前节点的右子节点为空,那么就把传入的节点作为当前节点的右子节点
            if (rightNode == null) {
                rightNode = node;

                //递归遍历当前节点的右子树添加 node
            } else {
                rightNode.addNode(node);
            }
        }
    }

    //中序遍历
    public void midOrder() {
        if (leftNode != null) {
            leftNode.midOrder();
        }

        System.out.println(this);

        if (rightNode != null) {
            rightNode.midOrder();
        }

    }

    @Override
    public String toString() {
        return "Node [value=" + value + "]";
    }

    //返回1为查找成功,0为失败
    public int search(Node node, int x){
        Node cur = node;
        int z = -1;
        if(cur == null){
            z = 0;
            return z;
        }

        if(cur.value == x){
            z = 1;
            return z;
        }

        if(cur.value > x){
            cur = cur.leftNode;
            z = search(cur, x);
        }

        if(cur.value < x){
            cur = cur.rightNode;
            z = search(cur, x);
        }

        return z;
    }

    public int BSTasl(int d)//总权值,注意调用时d赋值为0
    {
        d++;
        int a = d;
        if (this.leftNode != null)
            d += this.leftNode.BSTasl(a);
        if (this.rightNode != null)
            d += this.rightNode.BSTasl(a);
        return d;
    }

    public void BSTaslplus(int x)
    {
        if(this == null)
            System.out.println("该二叉树不存在\n");
        else{
            System.out.println(this.BSTasl(0) * 1.0 / x);
        }
    }
}

下面是Main中相关的代码:

if(x.equals("4")){
            System.out.println("请输入需要查找的参赛队编号:");
            Scanner scanner6 = new Scanner(System.in);
            int y5 = scanner6.nextInt();
            int judge = tree.search(tree, y5);
            if(judge == 1){
                System.out.println("查找成功!");
                int z = -1;
                for(int i = 0; i < array.length; i++){
                    if(array[i] == y5){
                        z = i;
                    }
                }
                System.out.println("您所需查找的信息如下:" + '\n');
                for(int i = 0; i < 6; i++){
                    System.out.println(sign[0][i] + ":" + sign[z + 1][i]);
                }
                System.out.println('\n' + "ASL的公式为:总权值(即每层的结点数×当前层数)/总结点数");
                System.out.println("平均查找长度ASL为:");
                tree.BSTaslplus(List01.size() - 1);
            }
            else{
                System.out.println("查找失败!编号不存在!");
            }
        }

第三模块的预习报告

——按赛事类别和参赛学校查找

1.问题定义

        查找与排序问题

2.问题分析

        此模块分为几个问题:

                1、如何按赛事类别查找?

                2、如何按参赛学校查找?

                3、如何进行排序?选用什么方法排序?

        对于第一第二个问题,很简单。我用来存放数据的数据结构是二维String数组,每个队伍的6个信息类别对应一行6个长度,很容易查找。

        排序我选用的是希尔排序,很常见的方法,就不说了。

3.概要设计

下面是Main中的代码:

if(x.equals("5")){
            System.out.println("请输入需要查找的赛事类别:");
            Scanner scanner7 = new Scanner(System.in);
            String y6 = scanner7.next();
            int[] a = new int[100];
            int c = 0;
            for(int i = 1; i < List01.size(); i++){
                if(Objects.equals(y6, sign[i][3])){
                    a[c] = Integer.parseInt(sign[i][0]);
                    c++;
                }
            }

            if(c != 0){
                for(int gap=c/2; gap>0; gap/=2) {
                    //从第gap个元素开始,逐个对其所在的组进行插入排序
                    for(int i=gap;i<c;i++) {
                        int j=i;
                        int temp=a[j];
                        if(a[j]<a[j-gap]) {
                            while(j-gap >= 0 && temp < a[j-gap]) {
                                //移动
                                a[j]=a[j-gap];
                                j-=gap;
                            }
                            //找到位置
                            a[j]=temp;
                        }
                    }
                }
                System.out.println("所有符合的对应信息如下:" + '\n');
                for(int i = 0; i < c; i++){
                    for( int j = 1; j < List01.size(); j++){
                        if (a[i] == Integer.parseInt(sign[j][0])) {
                            System.out.println('\n' + "第" + (i+1) + "个:");
                            for(int k = 0; k < 6; k++){
                                System.out.println(sign[0][k] + ":" + sign[j][k]);
                            }
                        }
                    }
                }
            }
            else{
                System.out.println("没有这个类别!");
            }
        }

        if(x.equals("6")){
            System.out.println("请输入需要查找的参赛学校:");
            Scanner scanner7 = new Scanner(System.in);
            String y6 = scanner7.next();
            int[] a = new int[100];
            int c = 0;
            for(int i = 1; i < List01.size(); i++){
                if(Objects.equals(y6, sign[i][2])){
                    a[c] = Integer.parseInt(sign[i][0]);
                    c++;
                }
            }

            if(c != 0){
                for(int gap=c/2; gap>0; gap/=2) {
                    //从第gap个元素开始,逐个对其所在的组进行插入排序
                    for(int i=gap;i<c;i++) {
                        int j=i;
                        int temp=a[j];
                        if(a[j]<a[j-gap]) {
                            while(j-gap >= 0 && temp < a[j-gap]) {
                                //移动
                                a[j]=a[j-gap];
                                j-=gap;
                            }
                            //找到位置
                            a[j]=temp;
                        }
                    }
                }
                System.out.println("所有符合的对应信息如下:");
                for(int i = 0; i < c; i++){
                    for( int j = 1; j < List01.size(); j++){
                        if (a[i] == Integer.parseInt(sign[j][0])) {
                            System.out.println('\n' + "第" + (i+1) + "个:");
                            for(int k = 0; k < 6; k++){
                                System.out.println(sign[0][k] + ":" + sign[j][k]);
                            }
                        }
                    }
                }
            }
            else{
                System.out.println("没有这所学校!");
            }
        }

第四模块的预习报告

——决赛叫号系统

1.问题定义

        对于自定义类的添加、查找和输出

2.问题分析

        此模块主要有下列几个问题:

                1.赛事怎么分类?

                2.怎么叫号?

        这一模块其实很简单。在课程设计的群中,老师发布了计算机设计大赛的类别安排表,根据表来进行大类的分类即可。比如,大数据应用这一大类中只有大数据实践这一小类,那么我们在总表中利用前面的算法来查找大数据实践的各个队伍,将他们在二维String数组中的下标位置储存起来,这样在叫号时就可实现该类的按顺序进场,模拟决赛。储存下标位置的是一个数组,我在定义的java类中用一个结构实现了,结构如下:

public String Category;
    public String RoomName;
    public int[] a = new int[100];
    public int a_l;

3.概要设计

        此模块比较简单,我用一个java类将之实现了。其中值得一提的是,我觉得一共9个决赛室一起叫号太过混乱,于是又在这个Room.java中添加了一个choose函数,用来供用户选择1-9中第几个决赛室叫号,按0则一起输出。另外,为了模拟真实场景,我设置每次叫一个队伍后,都要停顿1秒,用sleep实现,然后输出“该组所用时间为:”,后面加一个random生成的0-3的随机数,来表示所用时间。

        下面是完整Room.java:

package org.example;

import java.awt.desktop.ScreenSleepEvent;
import java.util.Objects;
import java.util.Scanner;

public class Room {
    public String Category;
    public String RoomName;
    public int[] a = new int[100];
    public int a_l;

    public Room(){
        Category = "无赛事类别!";
        RoomName = "无决赛室名字!";
        a_l = 0;
    }

    public void Create(String name, String cate){
        setRoomName(name);
        setCategory(cate);
        a_l = 0;
    }

    public void setRoomName(String name){
        RoomName = name;
    }

    public void setCategory(String category){
        this.Category = category;
    }

    public void add(String x, String[][] s){
        for(int i = 1; i < 398; i++){
            if(Objects.equals(x, s[i][3])){
                a[a_l] = i;
                a_l++;
            }
        }
    }

    public void call(String[][] s){
        System.out.println("以下为“" + this.RoomName + "”的决赛叫号顺序:" + '\n');
        for(int i = 0; i < a_l; i++){
            System.out.println("注意!!!请“第" + (i + 1) + "组”进入“" + this.RoomName + "”进行决赛!注意!此决赛室的赛事大类别为“" + this.Category + "”,队伍信息如下:");
            for(int j = 0; j < 6; j++){
                System.out.println(s[0][j] + ":" + s[a[i]][j]);
            }

            try {
                Thread.sleep(1 * 1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            double time = (double) Math.random()*3;
            System.out.println("该组所用时间为:" + time + '\n');
            System.out.println("第" + (i + 1) + "组已完成决赛!!!请第" + (i + 2) + "组做好准备!" + '\n');
        }
    }

    public void choose(int x, String[][] s){
        String k = "决赛室" + x;
        if(Objects.equals(k, RoomName) || x == 0){
            call(s);
        }
    }
}

下面是Main里面的相关代码:

if(x.equals("7")){
            //决赛室1
            Room room1 = new Room();
            room1.Create("决赛室1", "大数据应用");
            room1.add("大数据实践", sign);

            //决赛室2
            Room room2 = new Room();
            room2.Create("决赛室2", "信息可视化设计");
            room2.add("信息图形设计", sign);
            room2.add("动态信息影像(MG 动画)", sign);
            room2.add("交互信息设计", sign);
            room2.add("数据可视化", sign);

            //决赛室3
            Room room3 = new Room();
            room3.Create("决赛室3", "人工智能应用");
            room3.add("人工智能实践赛(普通赛道)", sign);

            //决赛室4
            Room room4 = new Room();
            room4.Create("决赛室4", "软件应用与开发");
            room4.add("Web 应用与开发", sign);
            room4.add("管理信息系统", sign);
            room4.add("算法设计与应用", sign);
            room4.add("移动应用开发(非游戏类)", sign);

            //决赛室5
            Room room5 = new Room();
            room5.Create("决赛室5", "物联网应用");
            room5.add("医药卫生", sign);
            room5.add("数字生活", sign);
            room5.add("运动健身", sign);
            room5.add("城市管理", sign);
            room5.add("行业应用", sign);

            //决赛室6
            Room room6 = new Room();
            room6.Create("决赛室6", "数媒动漫与短片(普通组+专业组)");
            room6.add("动画", sign);
            room6.add("纪录片", sign);
            room6.add("数字短片", sign);
            room6.add("微电影", sign);
            room6.add("新媒体漫画", sign);

            //决赛室7
            Room room7 = new Room();
            room7.Create("决赛室7", "数媒静态设计(普通组+专业组)");
            room7.add("产品设计", sign);
            room7.add("环境设计", sign);
            room7.add("平面设计", sign);

            //决赛室8
            Room room8 = new Room();
            room8.Create("决赛室8", "数媒游戏与交互设计(普通组+专业组)");
            room8.add("交互媒体设计", sign);
            room8.add("游戏设计", sign);
            room8.add("虚拟现实 VR 与增强现实 AR", sign);

            //决赛室9
            Room room9 = new Room();
            room9.Create("决赛室9", "微课与教学辅助");
            room9.add("汉语言文学(唐诗宋词)微课", sign);
            room9.add("计算机基础与应用类课程微课", sign);
            room9.add("虚拟实验平台", sign);
            room9.add("中、小学数学或自然科学课程微课", sign);

            //选择哪个决赛室
            System.out.println("各决赛室的赛事大类别如下所示:");
            System.out.println(room1.RoomName + ":" + room1.Category);
            System.out.println(room2.RoomName + ":" + room2.Category);
            System.out.println(room3.RoomName + ":" + room3.Category);
            System.out.println(room4.RoomName + ":" + room4.Category);
            System.out.println(room5.RoomName + ":" + room5.Category);
            System.out.println(room6.RoomName + ":" + room6.Category);
            System.out.println(room7.RoomName + ":" + room7.Category);
            System.out.println(room8.RoomName + ":" + room8.Category);
            System.out.println(room9.RoomName + ":" + room9.Category);
            System.out.println("请输入您想要输出的决赛室号,若输入0则全部输出:");
            Scanner scanner00 = new Scanner(System.in);
            int p = scanner00.nextInt();
            room1.choose(p, sign);
            room2.choose(p, sign);
            room3.choose(p, sign);
            room4.choose(p, sign);
            room5.choose(p, sign);
            room6.choose(p, sign);
            room7.choose(p, sign);
            room8.choose(p, sign);
            room9.choose(p, sign);
        }

第五模块的预习报告

——校园导游程序

1.问题定义

        校园导游咨询

2.问题分析

        经典的图论问题,求带权无向图中的两点之间的最短路径,并进行路径的打印和最短路径值的输出。

        此模块的问题在于:

                1.带权图怎么转化输入计算机?

                2.怎么求得任意两点的最短路径?

        带权图的输入,一般的方法有两种,一种是邻接矩阵,一种是邻接图。我从中选择了邻接矩阵。

        关于求得最短路径的算法,一般的算法有迪杰斯特拉(Dijkstra)和弗洛伊德(Floyd)算法。

        其中 Dijkstra 算法求的是单源最短路径:即从一个结点出发到其它所有结点的最短路径,算法的时间复杂度为 O(n 2 )。

        Floyd 算法求的是多源最短路径:即从任意结点出发到其它所有结点的最短路径,算法的时间复杂度为 O(n 3 )。

        前者的优点是时间复杂度小,但是无法直接得到我们需要的结果,需要进行修改。而后者的优点是可以直接获得我们需要的结果,不过缺点就是复杂度大。

        由于本人对于后者没有那么熟悉,加上迪杰斯特拉的时间复杂度更小所以我选用了迪杰斯特拉(Dijkstra)算法来实现。

        整个算法的实现较为繁琐,但是经典的迪杰斯特拉算法,在此就不细说了,大差不差。

        以下是实现迪杰斯特拉的java类:

        ShortestPathDijkstra.java:

package org.example;

import java.util.ArrayList;
import java.util.List;

public class ShortestPathDijkstra {

    /** 邻接矩阵 */
    private int[][] matrix;
    /** 表示正无穷 */
    private int MAX_WEIGHT = Integer.MAX_VALUE;
    /** 顶点集合 */
    private String[] vertexes;

    /**
     * 创建图2
     */
    private void createGraph2(int index) {
        matrix = new int[index][index];
        vertexes = new String[index];

        int[] v0 = { 0, 1, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
        int[] v1 = { 1, 0, 3, 7, 5, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
        int[] v2 = { 5, 3, 0, MAX_WEIGHT, 1, 7, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT };
        int[] v3 = { MAX_WEIGHT, 7, MAX_WEIGHT, 0, 2, MAX_WEIGHT, 3, MAX_WEIGHT, MAX_WEIGHT };
        int[] v4 = { MAX_WEIGHT, 5, 1, 2, 0, 3, 6, 9, MAX_WEIGHT };
        int[] v5 = { MAX_WEIGHT, MAX_WEIGHT, 7, MAX_WEIGHT, 3, 0, MAX_WEIGHT, 5, MAX_WEIGHT };
        int[] v6 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 3, 6, MAX_WEIGHT, 0, 2, 7 };
        int[] v7 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 9, 5, 2, 0, 4 };
        int[] v8 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 7, 4, 0 };
        matrix[0] = v0;
        matrix[1] = v1;
        matrix[2] = v2;
        matrix[3] = v3;
        matrix[4] = v4;
        matrix[5] = v5;
        matrix[6] = v6;
        matrix[7] = v7;
        matrix[8] = v8;

        vertexes[0] = "v0";
        vertexes[1] = "v1";
        vertexes[2] = "v2";
        vertexes[3] = "v3";
        vertexes[4] = "v4";
        vertexes[5] = "v5";
        vertexes[6] = "v6";
        vertexes[7] = "v7";
        vertexes[8] = "v8";
    }

    /**
     * 创建图1
     */
    public void createGraph1(int index) {
        matrix = new int[index][index];
        vertexes = new String[index];

        int[] v0 = { 0, MAX_WEIGHT, 3, MAX_WEIGHT, MAX_WEIGHT, 18, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT};
        int[] v1 = { MAX_WEIGHT, 0, MAX_WEIGHT, MAX_WEIGHT, 8, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 8, 7};
        int[] v2 = { MAX_WEIGHT, MAX_WEIGHT, 0, MAX_WEIGHT, 20, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT};
        int[] v3 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 0, MAX_WEIGHT, MAX_WEIGHT, 4, MAX_WEIGHT, MAX_WEIGHT, 6};
        int[] v4 = { MAX_WEIGHT, MAX_WEIGHT, 20, MAX_WEIGHT, 0, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 4, MAX_WEIGHT};
        int[] v5 = { 18, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 0, MAX_WEIGHT, 3, 3, MAX_WEIGHT};
        int[] v6 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 4, MAX_WEIGHT, MAX_WEIGHT, 0, 1, MAX_WEIGHT, 5};
        int[] v7 = { MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, MAX_WEIGHT, 3, 1, 0, MAX_WEIGHT, MAX_WEIGHT};
        int[] v8 = { MAX_WEIGHT, 8, MAX_WEIGHT, MAX_WEIGHT, 4, 3, MAX_WEIGHT, MAX_WEIGHT, 0, 8};
        int[] v9 = { MAX_WEIGHT, 7, MAX_WEIGHT, 6, MAX_WEIGHT, MAX_WEIGHT, 5, MAX_WEIGHT, 8, 0};

        matrix[0] = v0;
        matrix[1] = v1;
        matrix[2] = v2;
        matrix[3] = v3;
        matrix[4] = v4;
        matrix[5] = v5;
        matrix[6] = v6;
        matrix[7] = v7;
        matrix[8] = v8;
        matrix[9] = v9;

        vertexes[0] = "北门";
        vertexes[1] = "南门";
        vertexes[2] = "北苑";
        vertexes[3] = "西苑";
        vertexes[4] = "东苑";
        vertexes[5] = "文理大楼";
        vertexes[6] = "明德楼";
        vertexes[7] = "经世楼";
        vertexes[8] = "笃学楼";
        vertexes[9] = "体育中心";
    }

    /**
     * Dijkstra最短路径。
     *
     * vs -- 起始顶点(start vertex) 即,统计图中"顶点vs"到其它各个顶点的最短路径。
     */
    public void dijkstra(int vs, int z) {
        // flag[i]=true表示"顶点vs"到"顶点i"的最短路径已成功获取
        boolean[] flag = new boolean[vertexes.length];
        // U则是记录还未求出最短路径的顶点(以及该顶点到起点s的距离),与 flag配合使用,flag[i] == true 表示U中i顶点已被移除
        int[] U = new int[vertexes.length];
        // 前驱顶点数组,即,prev[i]的值是"顶点vs"到"顶点i"的最短路径所经历的全部顶点中,位于"顶点i"之前的那个顶点。
        int[] prev = new int[vertexes.length];
        // S的作用是记录已求出最短路径的顶点
        String[] S = new String[vertexes.length];

        // 步骤一:初始时,S中只有起点vs;U中是除vs之外的顶点,并且U中顶点的路径是"起点vs到该顶点的路径"。
        for (int i = 0; i < vertexes.length; i++) {
            flag[i] = false; // 顶点i的最短路径还没获取到。
            U[i] = matrix[vs][i]; // 顶点i与顶点vs的初始距离为"顶点vs"到"顶点i"的权。也就是邻接矩阵vs行的数据。

            prev[i] = 0; //顶点i的前驱顶点为0
        }

        // 将vs从U中“移除”(U与flag配合使用)
        flag[vs] = true;
        U[vs] = 0;
        // 将vs顶点加入S
        S[0] = vertexes[vs];
        // 步骤一结束

        //步骤四:重复步骤二三,直到遍历完所有顶点。
        // 遍历vertexes.length-1次;每次找出一个顶点的最短路径。
        int k = 0;
        for (int i = 1; i < vertexes.length; i++) {
            // 步骤二:从U中找出路径最短的顶点,并将其加入到S中(如果vs顶点到x顶点还有更短的路径的话,那么
            // 必然会有一个y顶点到vs顶点的路径比前者更短且没有加入S中
            // 所以,U中路径最短顶点的路径就是该顶点的最短路径)
            // 即,在未获取最短路径的顶点中,找到离vs最近的顶点(k)。
            int min = MAX_WEIGHT;
            for (int j = 0; j < vertexes.length; j++) {
                if (flag[j] == false && U[j] < min) {
                    min = U[j];
                    k = j;
                }
            }

            //将k放入S中
            S[i] = vertexes[k];

            //步骤二结束


            //步骤三:更新U中的顶点和顶点对应的路径
            //标记"顶点k"为已经获取到最短路径(更新U中的顶点,即将k顶点对应的flag标记为true)
            flag[k] = true;

            //修正当前最短路径和前驱顶点(更新U中剩余顶点对应的路径)
            //即,当已经"顶点k的最短路径"之后,更新"未获取最短路径的顶点的最短路径和前驱顶点"。
            for (int j = 0; j < vertexes.length; j++) {
                //以k顶点所在位置连线其他顶点,判断其他顶点经过最短路径顶点k到达vs顶点是否小于目前的最短路径,是,更新入U,不是,不做处理
                int tmp = (matrix[k][j] == MAX_WEIGHT ? MAX_WEIGHT : (min + matrix[k][j]));
                if (flag[j] == false && (tmp < U[j])) {
                    U[j] = tmp;
                    //更新 j顶点的最短路径前驱顶点为k
                    prev[j] = k;
                }
            }
            //步骤三结束
        }
        //步骤四结束

        // 打印dijkstra最短路径的结果
        System.out.print(vertexes[vs] + " 到 " + vertexes[z] + "的最短路径值为:" + U[z] + "  最短路径为:");
        List<String> path = new ArrayList<>();
        int j = z;
        while (true) {
            path.add(vertexes[j]);

            if (j == 0)
                break;

            j = prev[j];
        }

        path.remove(path.size() - 1);
        path.add(path.size(), vertexes[vs]);
        for (int x = path.size()-1; x >= 0; x--) {
            if (x == 0) {
                System.out.println(path.get(x));
            }
            else {
                System.out.print(path.get(x) + "->");
            }
        }

    }

}

        下面是Main中相关的代码:

if(x.equals("8")){
            System.out.println("江苏科技大学有以下10个地点可供查询:");
            System.out.println("1.北门 2.南门 3.北苑 4.西苑 5.东苑 6.文理大楼 7.明德楼 8.经世楼 9.笃学楼 10.体育中心");
            System.out.println("请依次输入起点和终点:");
            System.out.println("起点:");
            Scanner scanner5 = new Scanner(System.in);
            int t1 = scanner5.nextInt();
            System.out.println("终点:");
            Scanner scanner55 = new Scanner(System.in);
            int t2 = scanner55.nextInt();
            ShortestPathDijkstra dij = new ShortestPathDijkstra();
            dij.createGraph1(10);

            dij.dijkstra(t1 - 1, t2 - 1);
        }

        下面是我自己制作和赋权的校园带权图:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
【项目介绍】 数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip 数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip 数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip 数据结构新项目-基于C和C++实现的大学校园导游管理系统源码(含超详细注释).zip 【说明】 1、项目源码在上传前,都经过本地成功运行,功能测试无误。请放心下载使用!有问题请及时沟通交流。 2、适用人群:算机科学、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、机械电子信息等相关专业背景的在校大学生、专业老师 行业从业人员等下载使用。 3、用途:项目代表性强,具有创新性和启发性,故具有挺高的学习借鉴价值。不仅适合小白入门进阶,还可作为毕项目、课程设计、大作业、比赛初期项目立项演示等。 4、如果基础还不错,又热爱学习钻研,也可基于此项目基础上进行修改进行二次开发。 本人也是技术狂热者,如果觉得此项目对您有价值,欢迎下载使用! 无论您是运行还是二次开发,遇到问题或困惑,欢迎私信交流学习。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值