地铁最短路径代码分析
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
输出:
以上是关于地铁最短路径代码分析的主要内容,如果未能解决你的问题,请参考以下文章