地铁最短路径代码分析

Posted jgxjav

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了地铁最短路径代码分析相关的知识,希望对你有一定的参考价值。

地铁最短路径代码分析

相关链接:

https://github.com/jindsad/subwayDijkstra

实验要求说明:

根据实验要求,要实现5块部分。

1.导入txt中储存的地铁线路。

2.通过地铁线路生成地铁图,并记录每条线路的站点。

3.通过Dijkstra算法算出最短路径,储存在列表中。

4.遍历路径列表,记录线路转变,存入字符串。

5.将最短路径字符串导出txt。

模块分析:

保存站点和线路的类

站点类名Vertex包含属性有名字,相邻节点,所属线路,距离起始点最短路径,在最短路径中的上一个节点,是否已经被遍历。

public class Vertex {
    public final String name;
    public ArrayList<Vertex> neighbour=new ArrayList<Vertex>();
    public ArrayList<String> line=new ArrayList<String>();
    private int adjuDist;
    private Vertex parent;
    private boolean known=false;
}

 

线路类line包含线路名字,拥有的站点。

public class line {
    public final String name;
    public List<String> station;
            //=new ArrayList<String>()
    public line(String name,List<String> station){
        this.name = name;
        this.station = station;
    }
}

 

地铁输入txt文件格式

1号线:苹果园  ..
2号线:西直门 ..
4号线:宋河桥北 ..
5号线:宋家庄 ..
..

导入txt中储存的地铁线路

通过txt路径将地铁按行保存在List列表中,一行为一条线路。

方法名inputmapname

    public List<String>  inputmapname(String mapname){
          List<String> list = new ArrayList<String>();
          String line =new String();
        try (FileReader reader = new FileReader(mapname);
                BufferedReader br = new BufferedReader(reader);
           ) {
            while ((line = br.readLine()) != null) {
              if (line.lastIndexOf("---") < 0) {
                  list.add(line);
              }
          }
          return list;
           } catch (IOException e) {
               e.printStackTrace();
           }
        return null;
        
    }

 

通过地铁线路生成地铁图,并记录每条线路的站点

向线路添加站点

通过inputmapname方法将线路字符串存在list中,先用split将字符串按:分割,str[0]为名称,str[1]为站点。再将str[1]按“ ”分割得出每个站点名,将站点名保存在line类中,并用一个List station记录所有站点。station中的所有Vertex先不记录线路信息和相邻节点信息。

List<String> map=a.inputmapname(inputname);

for(int b=0;b<map.size();b++) {

//向线路加入站点
            List<String> s=new ArrayList<String>();
                String[] str;
                str = map.get(b).split(":");
                String[] sta;
                sta = str[1].split(" ");
                for(int st=0;st<sta.length;st++) {
                    s.add(sta[st]);
                }
                line li=new line(str[0],s);
                line.add(li);
                for(int st=0;st<sta.length;st++) {
                Vertex ve=new Vertex(sta[st]);
                int t=0;
                for(int op=0;op<station.size();op++) {
                    if(station.get(op).name.equals(sta[st])) {
                        t=1;
                        break;
                    }
                }
                if(t==0)station.add(ve);
            }

        }

 向站点传入相邻节点信息和所属站点

在传入线路时,已经将站点名存入station中,需要向站点添加相邻站点和线路,将txt文件重新导入,重新得到各线路站点,

将得到的站点遍历和station中进行比较,寻找出名字为sta[st+1]的站点和sta[st-1]的站点。并将寻找出String[st]对应的站点,将String[st+1]和String[st-1]对应的站点加入相邻站点中,并将站点对应的线路存入站点中

List<String> map=a.inputmapname(inputname);
for(int b=0;b<map.size();b++) {
//向线路加入站点
List<String> s=new ArrayList<String>();
String[] str;
str = map.get(b).split(":");
String[] sta;
sta = str[1].split(" ");
for(int st=0;st<sta.length;st++) {
int nu1=-1;
int nu2=-1;
for(int st1=0;st1<station.size();st1++) {
if(st>0&&station.get(st1).toName().equals(sta[st-1])) {
nu1=st1;
}
if(st<sta.length-1&&station.get(st1).toName().equals(sta[st+1])) {
nu2=st1;
}
if(nu2!=-1&&nu1!=-1)break;
}
for(int st1=0;st1<station.size();st1++) {
if(station.get(st1).toName().equals(sta[st])) {
if(nu1!=-1)station.get(st1).neighbour.add(station.get(nu1));
if(nu2!=-1)station.get(st1).neighbour.add(station.get(nu2));
station.get(st1).line.add(str[0]);
break;
}}}}

 

 去除一个节点的重复线路

技术图片

 

 

北京线路中会存在环形线路,我将这样的线路头尾用一个站点保存,使其构成环路,所以对站点添加线路名字时,会出现同一站点线路重复,所以需要去重,使用方法trimList去除相同元素。

 

    private static ArrayList trimList(ArrayList list) {
        ArrayList list2 = new ArrayList();
        for (int i = list.size() - 1; i >= 0; i--) {
        Object o = list.get(i);
        if (list2.indexOf(o) == -1) {
        list2.add(0, o);
        }
        }
        return list2;
        }

 

 通过Dijkstra算法算出最短路径,储存在列表中

用递归,当站点为空返回空,对站点v的相邻站点进行遍历,如果相邻点没有被访问过,就将其路径更改为v.getAdjuDist()+1 ,其父节点为v,如果相邻点的最短路径比v.getAdjuDist()+1 小这不做更改,如果相邻节点的最短路径比v.getAdjuDist()+1 ,更新最短路径为v.getAdjuDist()+1 。把所有相邻节点递归,直到所有节点遍历完成。

 private void updateChildren(Vertex v)
        {
         if (v==null) {
                return;
            }
         if(v.neighbour==null||v.neighbour.size()==0) {
             return;
         }
         List<Vertex> childrenList = new LinkedList<Vertex>();
         for(int a=0;a<v.neighbour.size();a++){
            if(v.getParent()==null||!v.getParent().equals(v.neighbour.get(a))) {
             Vertex childVertex=v.neighbour.get(a);
             if(!childVertex.isKnown())
                {
                    childVertex.setKnown(true);
                    childVertex.setAdjuDist(v.getAdjuDist()+1);
                    childVertex.setParent(v);
                    childrenList.add(childVertex);
                }
             int nowDist = v.getAdjuDist()+1;
             if(nowDist>=childVertex.getAdjuDist())
                {
                    continue;
                }
             else {
                    childVertex.setAdjuDist(nowDist);
                    childVertex.setParent(v);
                    childrenList.add(childVertex);
             }
             }
            
         }
         for(Vertex vc:childrenList)
            {
                updateChildren(vc);
            }
        }

 遍历路径列表,记录线路转变,存入字符串。

通过dijkstraTravasal输出最短路径站点,需要判断转站点。遍历每个ar的站点,用xian储存现在站点的线路,判断每个站点的前一个节点和后一个节点,如果站点改变则转成下一站点的线路,如果现有线路的xian改变,则也进行转站。将站点和转站线路保存在pa中用outputmap返回。

ar=dik.dijkstraTravasal(station, place1, place2);
String pa=String.valueOf(ar.size())+" ";

String xian="";

for(int num=0;num<ar.get(ar.size()-1).line.size();num++) {
                     for(int num1=0;num1<ar.get(ar.size()-2).line.size();num1++) {
                         if(ar.get(ar.size()-1).line.get(num).equals(ar.get(ar.size()-2).line.get(num1))) {
                             xian=ar.get(ar.size()-1).line.get(num);
                             break;
                         }
                         if(!xian.equals(""))break;
                     }
                }
                for(int num=ar.size()-1;num>=0;num--) {
                    int y=0;
                    pa=pa+ar.get(num).toName()+"
";
                    if(ar.get(num).line.size()>1&&num!=0&&num!=ar.size()-1){
                        for(int num1=0;num1<ar.get(num-1).line.size();num1++) {
                            for(int num2=0;num2<ar.get(num+1).line.size();num2++) {
                                if(ar.get(num-1).line.get(num1).equals(ar.get(num+1).line.get(num2))) {
                                    y=1;
                                    break;
                                }
                                if(y==1)break;
                            }
                        }
                        for(int num2=0;num2<ar.get(num-1).line.size();num2++) {
                        if(ar.get(num-1).line.get(num2).equals(xian)) {
                            break;
                        }
                        if(num2==ar.get(num-1).line.size()-1)y=0;
                        }
                        if(y==0) {
                            String hua="";
                            for(int num1=0;num1<ar.get(num).line.size();num1++) {
                                for(int num2=0;num2<ar.get(num-1).line.size();num2++) {
                                    if(ar.get(num).line.get(num1).equals(ar.get(num-1).line.get(num2))) {
                                        hua=ar.get(num-1).line.get(num2);
                                        xian=hua;
                                        break;
                                    }
                                    if(y==1)break;
                                }
                            }
                        pa=pa+hua+"
";
                        }
                    }
                }

 

-a输出line线路

        for(int b=0;b<line.size();b++) {
            if(line1.equals(line.get(b).name)) {
                for(int b1=0;b1<line.get(b).station.size();b1++) {
                    line2=line2+" "+line.get(b).station.get(b1);
                }
                break;
            }
        }

 

程序结果展示

输入:

-b 良乡大学城 双桥 -map C:UsersShineloneclipse-workspace软件工程个人作业src软件工程个人作业北京地铁图1.txt  -o C:UsersShineloneclipse-workspace软件工程个人作业src软件工程个人作业station.txt

 

输出:

技术图片技术图片

 

以上是关于地铁最短路径代码分析的主要内容,如果未能解决你的问题,请参考以下文章

软工个人项目——地铁最短路径分析

个人项目——地铁最短路径简要分析

北京地铁最短路径实现

个人项目——地铁线路的最短路径

个人项目1(地铁线路最短路径的程序)初步分析

地铁最短路径问题