地铁线路最短路径

1、主要功能

提供一副地铁线路图,计算指定两站之间最短(最少经过站数)乘车路线;输出指定地铁线路的所有站点。

具体需求:

  输入起始站点和目标站点并计算出乘车最短路径

  输出指定地铁线路的所有站点以及转站点的信息

错误处理:

  当输入错误信息时,会判断出错信息并给出错误原因,终止程序

 

以北京地铁为例,地铁线路信息保存在data.txt中,格式如下:

地铁线路总数
线路名1 站名1 站名2 站名3 ...
线路名2 站名1 站名2 站名3 ...
线路名3 站名1 站名2 站名3 ......

 

2、实现语言

java

 

3、实现算法

  对于该问题,我们要完成从地铁线路图中找到一条从某一起始站到达另一终点站的路径长度的最短路径,即经过的站点最少。那么我们解决这类问题最常用的算法有DFS/BFS算法、Floyd算法以及Dijksta算法。为简化分析,我们假设相邻两个站间的权重(即距离)相同,并忽略发车时间等各种信息,可以将有权图变为无权图。

在此基础上进行分析,最终采用BFS算法。

 

4、类职责划分

1、GraphModel

    String StationName;    //头节点
    List<String> stations; //相近节点
    List<String> LineName; //所在线路名称
    boolean isVisited = false;  

2、LineModel

    String LineName;      //线路名称
    List<String> stations;   //线路所含站点

3、ResultModel

    String startStation=null;   //当前站点
    String lastStation=null;    //上一站点

4、Main

  程序的入口,包含核心代码,以及BFS算法

5、DateInputing

  数据处理,将data.txt中的数据进行导入,并进行处理,建立邻接表。

 

5、核心代码

以下代码为简化代码,完整代码已上传至以下代码为简化代码,完整代码已上传至https://github.com/beyondor/Subway-shortLine

DateInputing

  1、读入数据

          //读入文件
          File filename = new File(pathname);
          InputStreamReader input = new InputStreamReader(new FileInputStream(filename));
          BufferedReader br = new BufferedReader(input);

   2、将线路信息以及站点信息的处理

            //存储线路信息
            tmpline.setLineName(tmpdata[0]);
            List<String> LineStation = new ArrayList<String>();
            for(int i=1;i<tmpdata.length;i++) {      
                LineStation.add(tmpdata[i]);     //该线路的所有站点
            }
            tmpline.setStations(LineStation);
            FinalLine.add(tmpline);

  3、将所有站点信息处理成邻接表

            //将线路信息处理成邻接表
            String tmp1 = tmpdata[1];
            String tmp2 = tmpdata[2];
            for(int i=2;i<tmpdata.length;i++) {     
                
                List<String> stations = new ArrayList<String>();
                List<String> LineName = new ArrayList<String>();
                List<String> stations1 = new ArrayList<String>();
                List<String> LineName1 = new ArrayList<String>();
                
                
                GraphModel graphstation = new GraphModel();
                GraphModel graphstation1 = new GraphModel();
                //判断tmp1是否是已经存储过
                int isExit = 0;
                int m = 0;
                for(int j=0;j<FinalGraph.size();j++) {
                    if(tmp1.equals(FinalGraph.get(j).getStationName())) {
                        isExit = 1;
                        m = j;      //tmp1在FinalGraph哪一个位置,存储到m中
                        break;
                    }
                }

                
                //判断tmp2是否是已经存储过
                int isExit1 = 0;
                int n = 0;
                for(int j=0;j<FinalGraph.size();j++) {
                    if(tmp2.equals(FinalGraph.get(j).getStationName())) {
                        isExit1 = 1;
                        n = j;
                        break;
                    }
                }

                int p=0;
                if(isExit==0&&isExit1==0) {          //tmp1未存储过,tmp2未存储过
                    graphstation.setStationName(tmp1);    //未存储过,新建graphstation类,将数据存入类中,最后压入FinalGraph类
                    LineName.add(tmpdata[0]);
                    stations.add(tmp2);
                    graphstation.setLineName(LineName);
                    graphstation.setStations(stations);
                    
                    graphstation1.setStationName(tmp2);
                    LineName1.add(tmpdata[0]);
                    stations1.add(tmp1);
                    graphstation1.setLineName(LineName1);
                    graphstation1.setStations(stations1);
                    
                    FinalGraph.add(graphstation);
                    FinalGraph.add(graphstation1);

                }
                else if(isExit==0&&isExit1==1) {          //tmp1未存储过,tmp2已存储过
                    graphstation.setStationName(tmp1);
                    LineName.add(tmpdata[0]);
                    stations.add(tmp2);
                    graphstation.setLineName(LineName);
                    graphstation.setStations(stations);
                    
                    List<String> station = FinalGraph.get(n).getStations();   //已存储过,则在FinalGraph第n个位置,在相邻战点后面加上
                    List<String> linename = FinalGraph.get(n).getLineName();
                    station.add(tmp1);
                    for(int t=0;t<linename.size();t++) {
                        if(tmpdata[0].equals(linename.get(t))) {
                            p=1;
                            break;
                        }
                    }
                    if(p==0)
                        linename.add(tmpdata[0]);
                    FinalGraph.get(n).setLineName(linename);
                    FinalGraph.get(n).setStations(station);
                    
                    FinalGraph.add(graphstation);
                }
                else if(isExit==1&&isExit1==0) {          //tmp1已存储过,tmp2未存储过
                    graphstation.setStationName(tmp2);
                    LineName1.add(tmpdata[0]);
                    stations1.add(tmp1);
                    graphstation.setLineName(LineName1);
                    graphstation.setStations(stations1);
                    
                    List<String> station = FinalGraph.get(m).getStations();
                    List<String> linename = FinalGraph.get(m).getLineName();
                    station.add(tmp2);
                    for(int t=0;t<linename.size();t++) {
                        if(tmpdata[0].equals(linename.get(t))) {
                            p=1;
                            break;
                        }
                    }
                    if(p==0)
                        linename.add(tmpdata[0]);
                    FinalGraph.get(m).setLineName(linename);
                    FinalGraph.get(m).setStations(station);
                    
                    FinalGraph.add(graphstation);
                }
                else if(isExit==1&&isExit1==1) {          //tmp1,tmp2都已存储过
                    List<String> station = FinalGraph.get(m).getStations();
                    List<String> linename = FinalGraph.get(m).getLineName();
                    station.add(tmp2);
                    for(int t=0;t<linename.size();t++) {
                        if(tmpdata[0].equals(linename.get(t))) {
                            p=1;
                            break;
                        }
                    }
                    if(p==0)
                        linename.add(tmpdata[0]);
                    FinalGraph.get(m).setLineName(linename);
                    FinalGraph.get(m).setStations(station);
                    
                    List<String> station1 = FinalGraph.get(n).getStations();
                    List<String> linename1 = FinalGraph.get(n).getLineName();
                    station1.add(tmp1);
                    for(int t=0;t<linename1.size();t++) {
                        if(tmpdata[0].equals(linename1.get(t))) {
                            p=1;
                            break;
                        }
                    }
                    if(p==0)
                        linename1.add(tmpdata[0]);
                    FinalGraph.get(n).setLineName(linename1);
                    FinalGraph.get(n).setStations(station1);
                    
                }
                tmp1=tmp2;
                if(i+1<tmpdata.length)
                    tmp2=tmpdata[i+1];
                else
                    break;
                
            }

Main

  1、BFS算法求最短路径

    public static List<ResultModel> BFS(String start,String end) {
        List<ResultModel> resultmodel = new ArrayList<ResultModel>();
        int flag=0;
        for(int i=0;i<dataProcessing.FinalGraph.size();i++) {
            if(end.equals(dataProcessing.FinalGraph.get(i).getStationName())) {
                flag=1;
                break;
            }
        }
        if(flag==0){
             System.out.print("终点站不存在");//判断终点站是否存在
             return null;
        }
        flag=0;
        for(int i=0;i<dataProcessing.FinalGraph.size();i++) {
            if(start.equals(dataProcessing.FinalGraph.get(i).getStationName())) {
                flag=1;
                break;
            }
        }
        if(flag==0){
            System.out.print("起点站不存在");//判断起点站是否存在
             return null;
        }
        if(end.equals(start)) {
            System.out.print("你已到达终点站");
             return null;
        }
        
        
        Queue<String> queue = new LinkedList<String>();
        queue.add(start);
        
        String last=null;
        
        ResultModel result = new ResultModel();        //结果类result存储BFS查找过的信息
        
        result.setLastStation(last);
        result.setStartStation(start);
        resultmodel.add(result);
        
        while(!queue.isEmpty()) {
            String tmp = queue.poll();  //队列头
            if(tmp.equals(end)) {       //当tmp是终站后跳出循环
                break;
            }
            
            int i = 0;
            for(i=0;i<dataProcessing.FinalGraph.size();i++) {      //找点站点
                if(tmp.equals(dataProcessing.FinalGraph.get(i).getStationName())) {
                    break;
                }
            }
            for(int j=0;j<dataProcessing.FinalGraph.get(i).getStations().size();j++) {   //该站点的相邻战点
                int p=0;
                for(int t=0;t<resultmodel.size();t++) {   //判断站点是否有入过队列
                    if(dataProcessing.FinalGraph.get(i).getStations().get(j).equals(resultmodel.get(t).getStartStation())){
                        p=1;
                        break;
                    }
                }
                if(p==0) {      
                    queue.add(dataProcessing.FinalGraph.get(i).getStations().get(j));
                    //将找到的临站放入结果集result,然后压入结果类resultmodel
                    result = new ResultModel();
                    result.setLastStation(tmp);
                    result.setStartStation(dataProcessing.FinalGraph.get(i).getStations().get(j));
                    resultmodel.add(result);
                    last=tmp;
                }
                
            }
            
        }
        
        return resultmodel;
    }

  2、输出最短路径(判断换乘站)

 

    public static void ShortLine(List<ResultModel> resultmodel,String start) {    //输出最短路径以及换乘信息
        
        String last=start;
        int num=0;
        List<String> shortpath = new ArrayList<String>();
        for(int i=resultmodel.size()-1;i>=0;i--) {                //得到最短路径结果,存入shortpath
            if(resultmodel.get(i).getStartStation().equals(last)) {
                shortpath.add(last);
                last=resultmodel.get(i).getLastStation();
                num++;
            }
        }
        
        //判断换乘信息
        String Line1 = null;       
        String nowLine = null;     //当前线路
        int t,t1;
        
        for(int i=0;i<shortpath.size()-1;i++) {
            for(t=0;t<dataProcessing.FinalGraph.size();t++) {
                if(dataProcessing.FinalGraph.get(t).getStationName().equals(shortpath.get(i))) {
                    break;
                }
            }
            for(t1=0;t1<dataProcessing.FinalGraph.size();t1++) {
                if(dataProcessing.FinalGraph.get(t1).getStationName().equals(shortpath.get(i+1))) {
                    break;
                }
            }
            int h=0;
            for(int m=0;m<dataProcessing.FinalGraph.get(t).getLineName().size();m++) {
                for(int j=0;j<dataProcessing.FinalGraph.get(t1).getLineName().size();j++) {
                    //找到当前栈和下一站的共同的线路,存入Line1
                    if(dataProcessing.FinalGraph.get(t).getLineName().get(m).equals(dataProcessing.FinalGraph.get(t1).getLineName().get(j))) {
                        if(i==0) {
                            nowLine=dataProcessing.FinalGraph.get(t).getLineName().get(m);
                            Line1=nowLine;
                            System.out.println();
                            System.out.println(nowLine);
                            System.out.print(shortpath.get(i)+"   ");
                        }
                        else
                            Line1=dataProcessing.FinalGraph.get(t).getLineName().get(m);
                        h=1;
                        break;
                    }
                }
                if(h==1)
                    break;
            }
            if(nowLine.equals(Line1)) {  //当前线路与后两站的线路相比较
                System.out.print(shortpath.get(i+1)+"   ");
            }
            else {
                nowLine=Line1;
                System.out.println("(换乘)");
                System.out.println(nowLine);
                System.out.print(shortpath.get(i+1)+"   ");
            }
        }
        
        
        
        System.out.println();
        System.out.println("共"+num+"站");
    }

 

  3、输出线路对应站点

    public static void searchLineData(String name) {         //依据线路名称查询站点
        int tmp=0;
        for(int i=0;i<dataProcessing.FinalLine.size();i++) {
            if(name.equals(dataProcessing.FinalLine.get(i).getLineName())) {
                for(int j=0;j<dataProcessing.FinalLine.get(i).getStations().size();j++) {
                    System.out.print(dataProcessing.FinalLine.get(i).getStations().get(j) + "  ");
                    tmp++;
                }
                break;
            }
        }
        if(tmp==0)
            System.out.println("线路不存在");
    }

 

  4、main函数

 

    public static void main(String[] args) {
    // TODO Auto-generated method stub
        Scanner input = new Scanner(System.in);
        try {
            dataProcessing = new DateInputing("E:\\data.txt");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        System.out.println("选择:1.查询路线;2.查询起点终点最短路径");
        int option1 = input.nextInt();
        while(option1!=1&&option1!=2) {
            System.out.println("选择:1.查询路线;2.查询起点终点最短路径");
            option1 = input.nextInt();
        }
        if(option1==1) {
            System.out.println("请输入路线名:");
            String name = input.next();
            //查询路线
            searchLineData(name);
        }
        else if(option1==2) {
            System.out.print("请输入起点:");
            String start = input.next();
            System.out.print("请输入终点:");
            String end = input.next();
            List<ResultModel> resultmodel = BFS(end,start);
            ShortLine(resultmodel,start);
        }
        input.close();
        
    }

 

 

 

 

6、测试用例

1、查找正常线路

 

 

 2、不存在的线路

 

 

 3、起点站不存在

 

 

 4、起始站与终点站相同

 

 

 5、不用换乘

 

 

 6、需要换乘

 

 

 

7、总结

  1.构建框架
  2.文件读入并且处理数据
  3.BFS算法(深度优先算法) 对数据的处理
  4.对换乘站的处理
  5.处理数据并输出结果
  通过本次实验,我发现我的算法复杂度比较大,代码冗余比较大,有很大的优化空间。自己的代码能力还是不足,需要不断地练习。

 

 

 

 

 
posted @ 2020-11-05 10:27  蜡笔的风间  阅读(877)  评论(1)    收藏  举报