地铁最短路径(完整版)

地铁最短路径

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

 

 

1.主要功能

1.实现一个支持显示地铁线路与计算换乘的程序
2.查询指定地铁线经过的站点
3.用户希望能获得以最少的站数从出发点到达目的地的路径

储存的读取文件格式

读入的文件后缀为txt(格式如下,为方便查看,将以表格的形式呈现)

sub.txt

线路名站点1站点2站点n
1号线 苹果园 古城 四惠东
2号线 西直门 积水潭 西直门
亦庄线 宋家庄 肖村 亦庄火车站

 

2.实现语言

java

3.实现算法

BFS(广度优先)

4.类职责划分

1.line类

    private String LineName;  //线名
    private List<String> stations= new ArrayList<String>();   //该线路中所有站

2.station类

    private String StationName;  //站点名
    private List<String> Line = new ArrayList<String>();  //所在线路(换乘站有多条)
    private List<station> LinkStations= new ArrayList<station>();  //与之相邻的站点
    private boolean visited;//是否访问过该站点
    private String preStation;//本站之前访问的站点
    private int distance=0;//本站距离起点站的站数
    private boolean ifchange;//是否换乘 默认为false 用于结果

3.Mymain类

    public static HashMap<String,station> map = new HashMap<>();//方便查找站点信息
    public static List<line> LineSet= new ArrayList<>();//方便查找路线

5.核心代码

1.getSubway   map和LineSet的初始化

    public static void getSubway(String filename) {//读入线路数据
        try {
            InputStreamReader reader = new InputStreamReader(new FileInputStream(filename));
            BufferedReader br = new BufferedReader(reader);
            String read = "";
            read = br.readLine();//线路数量
            int LineNum = 0;
            LineNum = Integer.parseInt(read);

            for (int i = 0; i <= LineNum; i++) {
                line linex = new line();//当前存的line
                read = br.readLine();
                if(read==null){
                    return;
                }
                String[] stations = read.split(" ");//读入的line对应的所有station
                linex.setLineName(stations[0]);//输入线路名
                if (stations.length<=1){
                    System.out.print("本线路无可乘站");
                    return;
                }
                for (int j = 1; j < stations.length - 1; j++) {
                    station station1 = new station();//当前line中的station
                    station station2 = new station();
                    if (map.containsKey(stations[j])) {//如果map中已经有该站点则把这个站点拿出来处理
                        station1 = map.get(stations[j]);
                        map.remove(stations[j]);
                    } else {
                        station1.setStationName(stations[j]);
                        station1.setVisited(false);
                    }

                    if (map.containsKey(stations[j + 1])) {//map中已经有该站后面的站点拿出来处理
                        station2 = map.get(stations[j + 1]);
                        map.remove(stations[j + 1]);
                    } else {
                        station2.setStationName(stations[j + 1]);
                        station2.setVisited(false);
                    }
                    if (!station1.getLine().contains(linex.getLineName()))//如果当前站未加入line中,则在line中当前站名
                        station1.AddStationLine(linex.getLineName());
                    if (!station2.getLine().contains(linex.getLineName()))//如果当前站未加入line中,则在line中当前站名
                        station2.AddStationLine(linex.getLineName());
                    if (!station1.getLinkStations().contains(station2))
                        station1.AddLinkStation(station2);
                    if (!station2.getLinkStations().contains(station1))
                        station2.AddLinkStation(station1);

                    station1.setPreStation(station1.getStationName());
                    station2.setPreStation(station2.getStationName());
                    map.put(stations[j], station1);//把station1重新放回map
                    map.put(stations[j + 1], station2);//把station2重新放回map
                    if (!linex.getStations().contains(station1.getStationName())) {
                        linex.stationAdd(station1.getStationName());
                    }
                    if (!linex.getStations().contains(station2.getStationName())) {
                        linex.stationAdd(station2.getStationName());
                    }
                }
                LineSet.add(linex);//把线路加入LineSet
            }
            br.close();
        }catch(Exception e){
            e.printStackTrace();
        }
    }

 

2.getStationOfLine   输出线路对应站点

public static void getStationOfLine(String name ){                             //根据线路名字查找该线路所有站点
        int flag = 0;
        int index = -1;
        for (line line1 :LineSet){
            index++;
            if(line1.getLineName().equals(name)) {
                flag = 1;
                break;
            }
        }
        if (flag==0)
            System.out.println("该地铁线路不存在");
        else {
            System.out.print(name + ": ");
            for (String str : LineSet.get(index).getStations()) {
                System.out.print(str + " ");
            }
        }
    }

3.BFS算法求最短路径

public static void BFS(String start,String end){
        int flagx = 0;
        if (!map.containsKey(start)){//判断起点站是否存在
            System.out.println("起点站不存在");
            flagx = 1;
        }
        if (!map.containsKey(end)){
            System.out.println("终点站不存在");//判断终点站是否存在
            flagx = 1;
        }
        if (flagx==1)
            return;
        for (String temp :map.keySet()){
            map.get(temp).setVisited(false);
            map.get(temp).setDistance(0);
        }
        station nowStation = new station();
        Queue<String> queue = new LinkedList<>();//存放遍历过的站点

        nowStation = map.get(start);
        queue.add(start);
        while(!queue.isEmpty()){
            String nowStationName = queue.poll();
            map.get(nowStationName).setVisited(true);
            if (nowStation.getStationName().equals(end)){
                break;
            }
            for (station station1 :map.get(nowStationName).getLinkStations()){
                if(!map.get(station1.getStationName()).isVisited()){//未访问过的临近站点
                    map.get(station1.getStationName()).setPreStation(nowStationName);//为preStation赋值
                    map.get(station1.getStationName()).setDistance(map.get(nowStationName).getDistance()+1);//临近站的距离为本站距离加1
                    queue.offer(station1.getStationName());
                }
            }
        }
    }

 

4.PrintPath   输出最短路径(判断换乘站)

public static void PrintPath(String start,String end){
        if (!map.containsKey(start)){//判断起点站是否存在
            return;
        }
        if (!map.containsKey(end)){
            return;
        }
        if (start.equals(end)){
            System.out.print("起点站与终点站相同 本站为"+end);
            return;
        }
        if(start.equals(end))
            return ;
        List<String> path = new ArrayList<>();
        Stack<String> printline = new Stack<>();
        int numStation = 1;//第几站
        int cnt = 0;//换乘次数
        String str = end;
        while(!str.equals(start)){
            path.add(str);
            printline.push(str);
            str = map.get(str).getPreStation();
        }
        path.add(str);//把start放入path
        printline.push(str);
        for (int i=1;i<path.size()-1;i++){
            if (map.get(path.get(i)).getLine().size()==1){
                continue;
            }
            String temp1="";
            String temp2="";
            for (String str1 : map.get(path.get(i)).getLine()){//本站与前一站的共同拥有的线路存在temp1中
                int flag=0;
                for (String str2 :map.get(path.get(i-1)).getLine()){
                    if (str1.equals(str2)){
                        temp1 = temp1+str1;
                        flag=1;
                        break;
                    }
                }
                if (flag==1)
                    break;
            }
            for (String str1 : map.get(path.get(i)).getLine()){//后一站与本站的共同拥有的线路存在temp2中
                int flag=0;
                for (String str2 :map.get(path.get(i+1)).getLine()){
                    if (str1.equals(str2)){
                        temp2 = temp2+str1;
                        flag=1;
                        break;
                    }
                }
                if (flag==1)
                    break;
            }
            if (!temp1.equals(temp2))//若temp1和temp2两线路不同则本站为转乘站
                map.get(path.get(i)).setIfchange(true);
        }//判断path中的换乘站
        System.out.println("共"+path.size()+"站");
        while(!printline.empty()){
            String printStation = printline.pop();
            if(numStation==1){
                for (String strnow : map.get(printStation).getLine()){
                    for (String nextStation : map.get(path.get(path.size()-numStation-1)).getLine()){
                        if (strnow.equals(nextStation)) {
                            System.out.println("当前线为:"+strnow);

                        }
                    }
                }
            }
            if (map.get(printStation).isIfchange()){
                String nowline ="";
                for (String strnow : map.get(printStation).getLine()){
                    //path.get(path.size()-numStation)换乘站下一站 两站共有的线路就是换乘到的线路
                    for (String nextStation : map.get(path.get(path.size()-numStation-1)).getLine()){
                        if (strnow.equals(nextStation))
                            nowline= nowline + strnow;
                    }
                }
                cnt++;
                System.out.println("");
                System.out.println("转线->"+nowline);
            }
            System.out.print(printStation+" ");
            numStation++;
        }
    }

 

5.main函数

public static void main(String[] ards){

        getSubway("C:\\Users\\41205\\IdeaProjects\\Java\\Subway\\src\\sub\\sub.txt");
        for (line linex: LineSet){
            System.out.print(linex.getLineName()+" ");
        }
        System.out.println("");
        System.out.println("1.查询线路(线路包含的所有站)");
        System.out.println("2.查询路线");
        System.out.print("请输入序号(1/2):");
        Scanner sc = new Scanner(System.in);
        int input = sc.nextInt();
        if (input==1){
            System.out.print("请输入线路名称:");
            Scanner sc1 = new Scanner(System.in);
            String linename = sc1.nextLine();
            getStationOfLine(linename);
        }
        else if (input==2){
            System.out.print("请输入起点站:");
            Scanner sc2 = new Scanner(System.in);
            String start =sc2.nextLine();
            System.out.print("请输入终点站:");
            String end = sc2.nextLine();
            BFS(start,end);
            PrintPath(start,end);
        }
        else
            System.out.println("请重新选择");
        return;
    }

6.测试用例

1.线路不存在

 2.正常查找线路

西郊线路查找

 5号线查找

 3.起点站终点站 同线路查找

 4.远程路线查找

5.起点站与终点站相同

 7.总结

1.构建框架

2.处理数据

3.BFS(深度优先算法) 进行对数据的处理(特别是换乘站的判断)

4.处理数据并输出结果

提高了我的java编程能力和写博客的能力

代码已全部传至https://github.com/zhangjunze1/Subway

posted @ 2020-11-02 19:07  馒头winner  阅读(614)  评论(0编辑  收藏  举报