北京地铁线路推荐项目

北京地铁线路推荐项目

一、项目介绍

Github:github.com/LinXS597/BeijingSubway

北京地铁线路推荐项目_第1张图片

二、需求分析

  1. 设计一个存储线路信息的文件
  2. 实现地铁线路信息的获取
  3. 实现基础查询功能,查询指定地铁线路经过的站点
  4. 实现出发地到目的地最短路径的查询

三、主要功能模块介绍

序号 模块名称 主要功能 对应Java文件
1 主模块 流程控制、参数解析 src/cn/edu/zucc/Main.java
2 核心算法模块 实现Dijkstra算法 src/cn/edu/zucc/core/DijkstraUtil.java
3 输入输出模块 读出和写入txt文件数据 src/cn/edu/zucc/data/FileManager.java
4 存储模块 存储读入的站点与线路信息 src/cn/edu/zucc/model/Station.java
存储输出的推荐线路信息 src/cn/edu/zucc/model/Routine.java

1、主模块:流程控制、参数解析

  • 支持采用参数 -map 作为标志,来获取对应的自定义地铁文件,例如:

    java subway -map subway.txt
  • 支持采用参数 -a 来指定地铁线路,采用参数 -o 来输出到指定文件station.txt,例如:

    java subway -a 1号线 -map subway.txt -o station.txt

  • 支持采用参数 -b 来指定出发地与目的地,例如:

    java subway -b 天安门西 北京大学东门 -map subway.txt -o routine.txt

2、核心算法模块:实现Dijkstra算法

  • 利用 HashMap 存储全部的站点信息,并以站点名称为key

    public static HashMap allStation = new HashMap<>();

  • 执行算法前先对数据进行预处理操作,主要目的有三个:
    1. 遍历各条线路信息,将station去除重复后加入allStation之中,便于后续算法执行
    2. 根据传入参数,确定并设置routine的起点与终点
    3. 对一些特殊情况进行处理,如起点终点重复、起点不存在、终点不存在等

具体代码如下

     public static Routine getRoutine ( String begin,String end)  {
        Routine routine = new Routine();
        List lineStationlist = null;


        Station station = null;
        Station repeatstation = null;

        for(String key:FileManager.subwayLineinfo.keySet()){    //遍历各条线路信息,将station去除重后加入allStation之中

            lineStationlist = FileManager.subwayLineinfo.get(key);

            for(int i = 0;i
  • 执行Dijkstra算法,主要有以下几步:
    1. 定义起点到其他顶点最短距离distance,定义某个指定站点的前一个站点path,并进行初始化
      HashMap,Integer> distance = new HashMap<>();
      HashMap path = new HashMap<>();
    2. 选择V,求的一个从起点到V的最短路径
    3. 修改从起点到任一顶点W可达的最短路径长度,以及W的父结点
    4. 重复2、3,求得最短距离

具体代码如下:

    public Routine Dijkstra_algorithm ( Routine routine ) {

        HashMap,Integer> distance = new HashMap<>();   //储存各站点之间的最短距离,以Integer为单位,表示站点数
        HashMap collected = new HashMap<>();                   //判断该Station是否被访问过
        HashMap path = new HashMap<>();                        //存储某个指定站点的前一个站点
        HashMap disitem = new HashMap<>();
        Station item;
        Station V;

        for (String key :allStation.keySet()){      //初始化distance、collected与path
            item = allStation.get(key);

            collected.put(item,new Integer(0));

            if (!routine.getBeginStation().equals(item)){
                if (routine.getBeginStation().getLinkStations().contains(item)){    //若与起点相邻,则将距离设置为1,并将对应的path设置为起点
                    disitem = new HashMap<>();
                    disitem.put(routine.getBeginStation(),item);
                    distance.put(disitem,new Integer(1));
                    path.put(item,routine.getBeginStation());
                }
                else{
                    disitem = new HashMap<>();                              //若未与起点相邻,则将初值设置为10000
                    disitem.put(routine.getBeginStation(),item);
                    distance.put(disitem,new Integer(10000));
                }
            }
            else{
                disitem = new HashMap<>();
                disitem.put(routine.getBeginStation(),item);
                distance.put(disitem,new Integer(0));
            }
        }

        collected.put(routine.getBeginStation(),1);

        while (true){
            V = FindMinDist(routine,distance,collected);    //取未被访问顶点中distance最小者
            if (V.getStationName().equals("-1"))            //若这样的V不存在,算法结束
                break;

            collected.put(V,1);

            for (String key:allStation.keySet()){           //遍历每个站点
                if (V.getLinkStations().contains(allStation.get(key))&&collected.get(allStation.get(key))==0){
                    if (distance.get(getFromtoFin(routine,V))+1

3、输入输出模块与存储模块:读出和写入txt文件数据

  • READ_FILE 和 WRITE_FILE 分别用于存储读入文件与输出文件路径信息
    public  static String READ_FILE;
    public  static String WRITE_FILE;
  • 利用HashMap存储线路数据

    public static HashMap> subwayLineinfo = new HashMap<>();

  • 存储站点信息的Station类设计

        private String stationName;     //站点名称

        private String lineName;        //线路名称

        private List linkStations = new ArrayList<>();     //相邻站点

  • 存储最短路径信息的Rountine类设计

        private Station beginStation;   //出发站点

        private Station endStation;     //结束站点

        private List passStations = new ArrayList<>();     //最短路径上的站点
  • 读入地铁线路与站点数据

subway.txt 文件设计如下:

    1号线 站点1 站点2 ...
    2号线 站点1 站点2 ...
    3号线 站点1 站点2 ...
    ...
  • 写入指定地铁线路的站点信息

station.txt 文件设计如下:

    1号线
    站点1
    站点2
    站点3
    ...
  • 写入指定站点之间的最短路径上的站点信息

routine.txt 文件设计如下:

    11
    天安门西
    西单
    复兴门
    --->换乘地铁--<2号线>--
    阜成门
    车公庄
    西直门
    --->换乘地铁--<13号线>--
    大钟寺
    知春路
    --->换乘地铁--<10号线>--
    知春里
    海淀黄庄
    --->换乘地铁--<4号线大兴线>--
    中关村
    北京大学东门

写入时需判断相邻的两个站点是否在同一条线路上,如果不在,则需更新线路信息并写入routine.txt中

    public static String getLineNmae(Station station1,Station station2){        //判断两个站点是否在同一条线路上
        String res = null;

        List item;
        
        for (String key : subwayLineinfo.keySet()){
            item = subwayLineinfo.get(key);
            if (item.contains(station1)&&item.contains(station2)){
                return key;     //如果是,返回线路名称,否则,返回null
            }

        }

        return res;
    }

四、测试分析

1) 重要功能测试

  1. 读入文件,命令行参数为:-map subway.txt

    • 测试结果:成功
  2. 查询线路,命令行参数为:-a 1号线 -map subway.txt -o station.txt

    • 测试结果:成功

2) 核心功能测试

  • 查询最短线路,命令行参数为:-b 天安门西 北京大学东门 -map subway.txt -o routine.txt

    • 测试结果:成功

3) 异常情况处理测试:

  1. 起点与终点相同:-b 天安门西 天安门西 -map subway.txt -o routine.txt

    • 显示提示信息:起点与终点相同
  2. 起点或终点不存在: -b 天安门西 杭州东站 -map subway.txt -o routine.txt

    • 显示提示信息:起点或终点不存在
  3. 查询线路不存在: -a 20号线 -map subway.txt -o station.txt

    • 显示提示信息:线路不存在
  4. 命令行参数格式错误: -f 天安门西 天安门西 -map subway.txt -o routine.txt

    • 显示提示信息:验证参数格式

你可能感兴趣的:(北京地铁线路推荐项目)