地铁最短路径

项目计划

实现一个通过地铁出行的最短路线规划的命令行程序。

主要功能

地图

描述已自动生成 

1.该程序能够读取.txt文件中的数据,格式如下:

地铁线路总数

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

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

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

2.提供详细的地铁信息查询:在某号线路上,能够查询各个站点的信息,输出该号线路上所有站点信息

3.提供最短路线的计算:在出发站与目的站之间寻求一个路线最短,时间最短,换地铁数最少的路线

项目完成预估表

Personal Software Process Stages Time

Time

计划

 

估计这个任务需要多少时间

1day

开发

 

· 需求分析 (包括学习新技术)

3day

· 生成设计文档

1day

· 具体设计

1day

· 具体编码

3day

· 代码复审

1day

· 测试(自我测试,修改代码,提交修改)

1day

报告

 

· 测试报告

1day

· 事后总结, 并提出过程改进计划

1day

 

实现语言

Java

实现算法

Dijkstra算法

类职责划分

· Result

该类用于存放结果

· Station

该类用于存放各站点信息

· Subway

主函数启动和输出

· Data

用于读取数据和图的创建

· route

Dijstra算法求最短路径

核心代码

 1 package model;
 2 
 3 public class Result {
 4  
 5       private Station start;  //起点站
 6       private Station end;    //终点站
 7       private Station pass;   //到达该站的最短路径中的上一站
 8       private String line;    //该站在几号线上
 9       private int distance;   //几站距离
10       private boolean change;   //是否需要换乘
11       public Result() {
12           
13       }
14     public Station getStart() {
15         return start;
16     }
17     public void setStart(Station start) {
18         this.start = start;
19     }
20     public Station getEnd() {
21         return end;
22     }
23     public void setEnd(Station end) {
24         this.end = end;
25     }
26     public Station getPass() {
27         return pass;
28     }
29     public void setPass(Station pass) {
30         this.pass = pass;
31     }
32     public String getLine() {
33         return line;
34     }
35     public void setLine(String line) {
36         this.line = line;
37     }
38     public int getDistance() {
39         return distance;
40     }
41     public void setDistance(int distance) {
42         this.distance = distance;
43     }
44     public boolean isChange() {
45         return change;
46     }
47     public void setChange(boolean i) {
48         this.change = i;
49     }
50 
51       
52 }
 1 package model;
 2 
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 
 6 public class Station {
 7     private String name;   //每个站点的名称
 8     private List<String> line = new ArrayList<String>();    //每一条地铁线路
 9     private List<Station> linkStations = new ArrayList<Station>();   //每一个站点中与之相邻的节点
10     public Station(String name, String linename) {
11         // TODO Auto-generated constructor stub
12         this.name=name;
13         this.line.add(linename);
14     }
15     public String getName() {
16         return name;
17     }
18     public void setName(String name) {
19         this.name = name;
20     }
21     public List<String> getLine() {
22         return line;
23     }
24     public void setLine(List<String> line) {
25         this.line = line;
26     }
27     public List<Station> getLinkStations() {
28         return linkStations;
29     }
30     public void setLinkStations(List<Station> linkStations) {
31         this.linkStations = linkStations;
32     }
33 }
public class Data {
    public Data(String pathname) throws IOException{
        File filename = new File(pathname); 
        InputStreamReader reader = new InputStreamReader(new FileInputStream(filename));  //读取地图文件
        BufferedReader br = new BufferedReader(reader); 
        String content="";
        content=br.readLine();  
        int linenum=Integer.parseInt(content);  //linenum为地图中地铁总线数
        for(int i=0;i<linenum;i++) {            //向图中添加地铁线路
            content=br.readLine();
            List<Station> line=new ArrayList<Station>();
            String[] linelist=content.split(" ");     //去空格
            String linename=linelist[0];      //读取线路的名称
            for(int j=1;j<linelist.length;j++) {  //向每条线路中添加站点
                int flag=0;
                for(List<Station> l:lineSet) {     //遍历线路集合
                    int t;
                    for(t=0;t<l.size();t++) {
                        if(l.get(t).getName().equals(linelist[j])) {    //寻找换乘站进行处理
                            List<String> changelist=l.get(t).getLine();
                            changelist.add(linename);   //向换乘列表内添加可以换乘的站点名字
                            l.get(t).setLine(changelist);
                            line.add(l.get(t));
                            flag=1;     //找到最近换乘点,跳出遍历
                            break;
                        }
                    }
                }
                if(linelist[j].equals(linelist[1])) {  //添加站点名和起始站点名一致时,判断其为环线
                    line.get(0).getLinkStations().add(line.get(line.size()-1));
                    line.get(line.size()-1).getLinkStations().add(line.get(0));
                    flag=1;
                }
                if(flag==0)
                    line.add(new Station(linelist[j],linename)); //既不是环线也不是换乘点直接添加
            }
            for(int j=0;j<line.size();j++) {  //添加每个车站相邻的车站
                List<Station> newlinkStations=line.get(j).getLinkStations();
                if(j==0) {                     //该站为起始站
                    newlinkStations.add(line.get(j+1));
                    line.get(j).setLinkStations(newlinkStations);
                }
                else if(j==line.size()-1) {   //该站为终点站
                    newlinkStations.add(line.get(j-1));
                    line.get(j).setLinkStations(newlinkStations);
                }
                else {                        //中间站
                    newlinkStations.add(line.get(j+1));
                    newlinkStations.add(line.get(j-1));
                    line.get(j).setLinkStations(newlinkStations);
                }
            }
            lineSet.add(line); 
        }
        br.close();
    }

}
 1 public class route {
 2     private static List<Station> listA= new ArrayList<>();  
 3     private static HashMap<Station, Result> resultMap = new HashMap<>();  //结果集
 4     private static Station getNextStation() {    
 5         int min=999999;               //初始化最短路径
 6         Station nextStation = null;
 7         Set<Station> stations = resultMap.keySet();
 8         for (Station station : stations) {
 9             if (listA.contains(station)) {    //过滤掉已经包含的站点名
10                 continue;
11             }
12             Result result = resultMap.get(station);
13             if (result.getDistance() < min) {   //判断其是否最短
14                 min = result.getDistance();
15                 nextStation = result.getEnd();
16             }
17         }
18         return nextStation;   
19     }    
20     
21     public static List<Station> getAllStation(String linename){  //获取路线上的全部站点
22         int flag=1;
23         for (List<Station> listall:Data.lineSet) {
24             for(Station s :listall) {
25                 if(!s.getLine().contains(linename))
26                     flag=0;
27             }
28             if(flag==1)
29                 return listall;
30             else
31                 return null;
32         }    
33         return null;
34     }
35     
36     public static Result shortestPath(Station start, Station end) {  //用dijstra算法计算最短路径
37         for(List<Station> l:Data.lineSet) {  //构造结果集
38             for(int i=0;i<l.size();i++) {
39                 Result result = new Result();
40                 result.setStart(start);
41                 result.setEnd(l.get(i));
42                 result.setDistance(999999);
43                 result.setChange(false);
44                 resultMap.put(l.get(i), result);
45             }
46         }
47         for(Station s:start.getLinkStations()) {  //初始化结果集
48             resultMap.get(s).setDistance(1);
49             resultMap.get(s).setPass(start);
50             List<String> changelines=getChangeLine(start.getLine(),s.getLine());
51             resultMap.get(s).setLine(changelines.get(0));
52         }
53         resultMap.get(start).setDistance(0);
54         listA.add(start);            //添加起始站
55         Station nextstation = getNextStation();     
56         while(nextstation!=null) {    //对每一个站点进行遍历,计算最短路径
57             for(Station s:nextstation.getLinkStations()) {
58                 if(resultMap.get(nextstation).getDistance()+1<resultMap.get(s).getDistance()) { 
59                     resultMap.get(s).setDistance(resultMap.get(nextstation).getDistance()+1);
60                     resultMap.get(s).setPass(nextstation);
61                     //判断是否在原来线路上,即是否需要换乘
62                     List<String> changelines=getChangeLine(nextstation.getLine(),s.getLine());
63                     if(!changelines.contains(resultMap.get(nextstation).getLine())) {  
64                         resultMap.get(s).setLine(changelines.get(0));
65                         resultMap.get(s).setChange(true);
66                     }
67                     else {
68                         resultMap.get(s).setLine(resultMap.get(nextstation).getLine());
69                     }
70                 }
71             }
72             listA.add(nextstation); 
73             nextstation = getNextStation();
74         }    
75         return resultMap.get(end);
76     }
77     
78 }

 

运行效果

通过-a命令显示一条线路上的所有站点

 

 

 

 

通过-b命令查询最短路径

1.同一条线路两站间查询

 

 

2.换乘查询

 

 

 

异常处理

 

 

 

总结

程序做起来还是比想象中更复杂一些,对java的各个类也有了更深入的了解,也更清晰的感受到了自己的不足。

整个程序基本能够正常运行,但还是存在较多漏洞,还有较多没考虑到的情况,还有待加强

Git地址

https://github.com/zzzmmmzzz/Subway