热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

图的最短路径java_地铁线路最短路径(JAVA实现)

项目综述提供一副地铁线路图,计算指定两站之间最短(最少经过站数)乘车路线;输出指定地铁线路的所有站点。以北京地铁为例,地铁线路信息保存在d

项目综述

6c3f258d2e4d136907687825b3b9a325.png

提供一副地铁线路图,计算指定两站之间最短(最少经过站数)乘车路线;输出指定地铁线路的所有站点。以北京地铁为例,地铁线路信息保存在data.txt中,格式如下:

地铁线路总数

线路名1 站名1 站名2 站名3 ...

线路名2 站名1 站名2 站名3 ...

线路名3 站名1 站名2 站名3 ......

一、需求分析

1.该程序能够准确地读出.txt文件中的数据,文件格式简洁易懂、可灵活扩展

2.在某号线路上,能够查询各个站点的信息,输出该号线路上所有站点信息

3.在出发站与目的站之间输出一个最短路径

二、实现语言

Java

三、实现算法

Floyd算法

四、类职责划分

1.SubwayAssistantStarter类

程序入口

2.GetData类

从data.txt中读取数据并存储各条线路和各个站点

3.Line类

privateString name;private List stations = new ArrayList();//该线路上的所有站点

//已省略Getter & Setter

4.Map类

private int[][] subwayline;//存储线路private static List stations;//存储所有站点private int[][] path;//存储路径

//已省略Getter & Setter

5.Result类

private static final int max = 999999;//最大距离

private int[][] ShortestPath;//最短路径

private int[][] ShortestDis;//最短距离

//已省略Getter & Setter

6.FrmMain类

ui主界面,包括功能选择和显示北京地铁线路背景图

7.FrmLine类 & FrmShowStations类

ui分页面

FrmLine类:用户需输入格式正确的线路名

FrmShowStation类:用户输入格式正确的线路名后弹窗显示具体线路信息

8.FrmShortestPath类 & FrmShowShortestPath类

ui分页面

FrmShortestPath类:用户输入格式正确的站点名

FrmShowShortestPath类:用户输入正确后弹窗显示两站间最短路径具体信息

五、核心代码

1.读取data.txt中的数据

public class GetData {//读取.txt文件中的信息

public static int linenum = 0;

@SuppressWarnings("null")public GetData(String pathname, List lines) throwsIOException{//读文件准备

File file = newFile(pathname);

InputStreamReader rdr= new InputStreamReader(newFileInputStream(file));

BufferedReader br= newBufferedReader(rdr);try{

String content=null;while((content=br.readLine())!=null) {

linenum++;

Line newline= newLine();

List line = new ArrayList();

String[] station_single= content.split(" ");

String linename= station_single[0];//第一个元素为线路名

for(int i=1;i

if(i==station_single.length-1 && station_single[i].equals(station_single[1]))//处理环线

continue;

line.add(station_single[i]);

}

newline.setName(linename);

newline.setStations(line);

lines.add(newline);

}

br.close();

}catch(IOException e) {

e.printStackTrace();

}finally{if (br == null)try{

br.close();

}catch(IOException e) {

e.printStackTrace();

}

}

}

}

2.Floyd算法求最短路径

public classResult {private static final int max = 999999;private int[][] ShortestPath;private int[][] ShortestDis;public Result(int[][] G) {this.ShortestPath = new int[G.length][G.length];this.ShortestDis = new int[G.length][G.length];for(int i=0;i

}

}//Floyd核心算法

for(int k=0;kthis.ShortestDis[i][k]+this.ShortestDis[k][j]) {this.ShortestDis[i][j]=this.ShortestDis[i][k]+this.ShortestDis[k][j];this.ShortestPath[i][j]=this.ShortestPath[i][k];

}

}

}

}

3.初始化整个地图

public Map(List stations) {//初始化整个地图

this.stations =stations;this.subwayline = new int[stations.size()][stations.size()];this.path = new int[stations.size()][stations.size()];for(int i=0;i

subwayline[i][j]= 999999;

subwayline[j][i]= 999999;

}

}

}

4.主页面显示功能与北京地铁线路背景图

public class FrmMain extends JFrame implementsActionListener{private static final long serialVersionUID = 1L;private JMenuBar menubar=newJMenuBar();private JPanel statusBar = newJPanel();private JMenu menu_Manager=new JMenu("功能");

JFrame jf&#61;newJFrame();private JMenuItem menuItem_Line&#61;new JMenuItem("查询线路");private JMenuItem menuItem_ShortestPath&#61;new JMenuItem("查询最短路径");private static List lines &#61; new ArrayList<>();//存储.txt中的所有数据

private List stations &#61; new ArrayList();//存储所有站点

public FrmMain() throwsIOException {//读文件

String filepath &#61; "E:\\Software Engineering\\data.txt";

GetData data&#61; newGetData(filepath,lines);//北京地铁图片

JLabel jl3&#61;new JLabel(new ImageIcon("E:\\Software Engineering\\subway.jpg"));

jf.add(jl3);

jl3.setBounds(0, 100, 80, 60);

jf.pack();

jf.setVisible(true);this.setTitle("北京地铁小助手");

menu_Manager.add(menuItem_Line);

menuItem_Line.addActionListener(this);

menu_Manager.add(menuItem_ShortestPath);

menuItem_ShortestPath.addActionListener(this);

menubar.add(menu_Manager);

statusBar.setLayout(newFlowLayout(FlowLayout.LEFT));

JLabel label&#61;new JLabel("欢迎使用北京地铁小助手^^");

statusBar.add(label);this.getContentPane().add(statusBar,BorderLayout.SOUTH);this.addWindowListener(newWindowAdapter(){public voidwindowClosing(WindowEvent e){

System.exit(0);

}

});this.setVisible(true);this.setJMenuBar(menubar);

}public voidactionPerformed(ActionEvent e) {if(e.getSource()&#61;&#61;this.menuItem_Line){

FrmLine dlg&#61;new FrmLine(this,"查询线路",true,lines);

dlg.setVisible(true);

}else if(e.getSource()&#61;&#61;this.menuItem_ShortestPath){

FrmShortestPath dlg&#61;new FrmShortestPath(this,"查询最短路径",true,lines,stations);

dlg.setVisible(true);

}

}

5.在查询页面处理最短路径

public class FrmShortestPath extends JDialog implementsActionListener{private List lines2 &#61; new ArrayList<>();//存储.txt中的所有数据

privateResult result;privateMap map;private List list1 &#61; new ArrayList<>(); //存储经过单个站点的地铁线的名字&#xff0c;以列表储存

private List> lists &#61; new ArrayList<>(); //存储经过所有站点的地铁线的名字&#xff0c;将list1依次添加进lists中

private List passStation &#61; new ArrayList<>(); //储存经过站点在数组中的下标

private JPanel toolBar &#61; newJPanel();private JPanel workPane &#61; newJPanel();private Button btnOk &#61; new Button("查询");private JTextField edtStart &#61; new JTextField(20);private JTextField edtEnd &#61; new JTextField(20);private JLabel labelStart &#61; new JLabel("起点:");private JLabel labelEnd &#61; new JLabel("终点:");private JLabel labelTip &#61; new JLabel("请输入您要查询的起点和终点^^");public FrmShortestPath(FrmMain frmMain, String s, boolean b, List lines, Liststations) {super(frmMain,s,b);

lines2.addAll(lines);

toolBar.setLayout(newFlowLayout(FlowLayout.RIGHT));

toolBar.add(btnOk);this.getContentPane().add(toolBar, BorderLayout.SOUTH);

workPane.add(labelStart);

workPane.add(edtStart);

workPane.add(labelEnd);

workPane.add(edtEnd);

workPane.add(labelTip);this.getContentPane().add(workPane, BorderLayout.CENTER);this.setSize(280, 150);double width &#61;Toolkit.getDefaultToolkit().getScreenSize().getWidth();double height &#61;Toolkit.getDefaultToolkit().getScreenSize().getHeight();this.setLocation((int) (width - this.getWidth()) / 2,

(int) (height - this.getHeight()) / 2);this.validate();this.btnOk.addActionListener(this);this.addWindowListener(newWindowAdapter() {public voidwindowClosing(WindowEvent e) {//System.exit(0);

}

});//把所有站点加入stations中

for(int i&#61;0;i

stations.addAll(lines.get(i).getStations());

}

map&#61; new Map(stations);//此map非彼map//初始化各个站点间的距离为1

for(int i&#61;0;i

map.initDis(lines.get(i).getStations().get(j), lines.get(i).getStations().get(j&#43;1));

}

}//求最短路径

result &#61; newResult(map.getSubwayline());

}

&#64;Overridepublic voidactionPerformed(ActionEvent e) {if(e.getSource()&#61;&#61;this.btnOk) {int flag1&#61;-1;int flag2&#61;-1;

String start&#61; this.edtStart.getText();

String end&#61; this.edtEnd.getText();

flag1&#61;FrmMain.isStation(start);

flag2&#61;FrmMain.isStation(end);if(start&#61;&#61;null || start.equals("") || end&#61;&#61;null || end.equals(""))try{throw newException();

}catch(Exception e1) {

JOptionPane.showMessageDialog(null, "起点/终点不能为空&#xff01;","错误",JOptionPane.ERROR_MESSAGE);return;

}else if(flag1<0 || flag2<0){try{throw newException();

}catch(Exception e1) {

JOptionPane.showMessageDialog(null, "起点/终点不存在&#xff01;","错误",JOptionPane.ERROR_MESSAGE);return;

}

}else if(start.equals(end)) {try{throw newException();

}catch(Exception e1) {

JOptionPane.showMessageDialog(null, "起点和终点不能相同&#xff01;","错误",JOptionPane.ERROR_MESSAGE);return;

}

}else{//查询shortest path

int i &#61;map.getIndex(start);int j &#61;map.getIndex(end);int shortest &#61; result.getMinDis(i,j);//需修改

if(shortest &#61;&#61; 999999) {try{throw newException();

}catch(Exception e1) {

JOptionPane.showMessageDialog(null, "两站点不可达&#xff01;","错误",JOptionPane.ERROR_MESSAGE);return;

}

}

shortest&#43;&#43;;

String path&#61; start&#43;"到"&#43;end&#43;"需经过"&#43;shortest&#43;"个站\n";

passStation&#61; result.indexToList(i,j);//存储最短路径

for(int k&#61;0;k

List list &#61; new ArrayList<>();

path&#43;&#61;(map.getName(passStation.get(k))&#43;"(");//System.out.println(path);

for(Line l:lines2) {int flag&#61;0;for(String name:l.getStations()) {

System.out.println(map.getName(passStation.get(i)));if(map.getName(passStation.get(i)).equals(name)){

path&#43;&#61;(l.getName()&#43;" ");

list.add(l.getName());if(!list1.contains(name)) {

list1.add(name);

flag&#61;1;

}

}

}if(flag&#61;&#61;1) lists.add(list);

}

}

path&#43;&#61;")";

path&#43;&#61;"\n";//存储换乘车站

List transfer &#61; new ArrayList<>();for(int p&#61;2;p

flag&#61;1;break;

}

}if(flag&#61;&#61;0) {if(!transfer.contains(list1.get(p-1))); transfer.add(list1.get(p-1));

}

}

path&#43;&#61;"\n";

path&#43;&#61;"需要换乘"&#43;transfer.size()&#43;"次&#xff1a;";for(int a&#61;0;a

path&#43;&#61;(transfer.get(a)&#43;" ");

}

path&#43;&#61;"\n";

FrmShowShortestPath dlg&#61;new FrmShowShortestPath(this,"最短路径详情",true,path);

dlg.setVisible(true);

}

}

}

}

六、测试用例

1.主界面

包括功能与北京地铁线路背景图

0318fa584596ad4561357aa1d93ec81d.png

2.查询线路

70dd3eb89684189ed010e03e503bd4e6.png

3.查询线路·输入为空

d815dd83a3c9bb69ea73f071fa5f10fa.png

4.查询线路·输入不存在的线路

ca2f0c1b55360cfe50bad3e2221713b6.png

5.查询最短路径·同线路

661a26406869e981070ad8181f7877d0.png

6.查询最短路径·远站需换乘

8cb2a539eb292ca380441ed03828d0fe.png

7.查询最短路径·起点/终点为空

c4118345c4a2f66a01ea271edb9cc4c0.png

6b42553bb26d2aafca624dfb1e47f21e.png

8.查询最短路径·输入站点不存在

191af632235bb6b5bdf5f71d6db27116.png

9.查询最短路径·起点终点相同

bca638c6dd24e139b2cb4e8588e66423.png

七、总结

1.在上一次的需求分析中原本打算用Dijstra算法&#xff0c;但是在写代码的过程中发现了Floyd算法更易实现&#xff0c;于是就果断跑路Floyd算法了&#xff0c;究其原因应该是需求分析不够深入&#xff0c;没有进一步结合代码实现来思考。

2.写代码的过程中&#xff0c;意识到多个UI界面弹窗之间传参数的麻烦之处&#xff0c;经过这一次的锻炼&#xff0c;对JAVA类与类之间传参数有了更好的理解。

3.认识到自己对JAVA还有许多不了解的“简便方法”&#xff0c;在本次写博客的过程中在CSDN中获益匪浅&#xff0c;希望以后也是多多锻炼&#xff0c;继续在CSND和Baidu中学习更多的知识。

4.至于前端UI&#xff0c;我还是以较为“偷懒”的方式用了在暑假短学期学到的JAVA Swing&#xff0c;算是对之前学习内容的一个复习与巩固叭。

5.算是第一次写这么完整的技术博客&#xff0c;也是一次不可多得的实战经验呢^^



推荐阅读
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了Swing组件的用法,重点讲解了图标接口的定义和创建方法。图标接口用来将图标与各种组件相关联,可以是简单的绘画或使用磁盘上的GIF格式图像。文章详细介绍了图标接口的属性和绘制方法,并给出了一个菱形图标的实现示例。该示例可以配置图标的尺寸、颜色和填充状态。 ... [详细]
  • 基于Socket的多个客户端之间的聊天功能实现方法
    本文介绍了基于Socket的多个客户端之间实现聊天功能的方法,包括服务器端的实现和客户端的实现。服务器端通过每个用户的输出流向特定用户发送消息,而客户端通过输入流接收消息。同时,还介绍了相关的实体类和Socket的基本概念。 ... [详细]
  • ***byte(字节)根据长度转成kb(千字节)和mb(兆字节)**parambytes*return*publicstaticStringbytes2kb(longbytes){ ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • 纠正网上的错误:自定义一个类叫java.lang.System/String的方法
    本文纠正了网上关于自定义一个类叫java.lang.System/String的错误答案,并详细解释了为什么这种方法是错误的。作者指出,虽然双亲委托机制确实可以阻止自定义的System类被加载,但通过自定义一个特殊的类加载器,可以绕过双亲委托机制,达到自定义System类的目的。作者呼吁读者对网上的内容持怀疑态度,并带着问题来阅读文章。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • 本文介绍了在Cpp中将字符串形式的数值转换为int或float等数值类型的方法,主要使用了strtol、strtod和strtoul函数。这些函数可以将以null结尾的字符串转换为long int、double或unsigned long类型的数值,且支持任意进制的字符串转换。相比之下,atoi函数只能转换十进制数值且没有错误返回。 ... [详细]
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • OpenMap教程4 – 图层概述
    本文介绍了OpenMap教程4中关于地图图层的内容,包括将ShapeLayer添加到MapBean中的方法,OpenMap支持的图层类型以及使用BufferedLayer创建图像的MapBean。此外,还介绍了Layer背景标志的作用和OMGraphicHandlerLayer的基础层类。 ... [详细]
author-avatar
784485886_fe0643
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有