第一模块的预习报告
——管理各队伍的参赛信息(增、删、改)
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);
}
下面是我自己制作和赋权的校园带权图: