地铁线路最短路径

主要内容:
1、主要功能
提供一副地铁线路图,计算指定两站之间最短(最少经过站数)乘车路线;输出指定地铁线路的所有站点。以北京地铁为例,地铁线路信息保存在data.txt中,格式如下:
地铁线路总数
线路名1 站名1 站名2 站名3 ...
线路名2 站名1 站名2 站名3 ...
线路名3 站名1 站名2 站名3 ...
2、实现语言
Java
3、实现算法
DFS算法,深度遍历算法
我的算法是基于无权图的最短路径的深度遍历算法而来,采用迭代的方式来解决问题。我创建了一个叫visit的二维数组,以站点的编号为参数,记录在迭代过程中是否经过了该条边。也创建了一个最小距离min,来记录过程中的路程最小值。同事还多创建了一个lu2的数组,用来更新最小的路径过程。
4、类职责划分
Main类:主函数,包含函数:主进程、提取数据、提取站点编号、DFS算法和输出。
主进程
`
public static void main(String[] args) throws IOException {
ArrayList<Station> station = new ArrayList<Station>(); //站点集合
int[][] bian = new int[400][400]; //边
ArrayList<Line> line = new ArrayList<Line>(); //线路集合
File file = new File("C:/Users/乐乐/Desktop/地铁线路信息.txt");
if(file.exists()) {
getShuju(file,station,bian,line); //导入数据
}
else
System.out.print("不存在");
Scanner s = new Scanner(System.in);
System.out.print("请输入起始站: ");
String start = s.next();
System.out.print("请输入终点站: ");
String end = s.next();
int n1 = getNum(station, start);
if(n1 == -1)
System.out.print("不存在该起点");
int n2 = getNum(station, end);
if(n2 == -1)
System.out.print("不存在该终点");
digist(station,n1,n2,bian,0); //DSF算法
System.out.println("最少站数: " +min);
shuChu(n1,station,line);
}
`
从TXT中提取数据
`
public static void getShuju(File file, ArrayList
String node = "UTF-8";
FileInputStream fin = new FileInputStream(file);
InputStreamReader reader = new InputStreamReader(fin,node);
BufferedReader br = new BufferedReader(reader);
int num = 22; //线路总数
for(int i = 0;i < num; i++) {
String token = br.readLine();
String[] tokens = token.split(" ");
String line = tokens[0]; //先储存线路信息
Line li = new Line(line);
Line.add(li);
for(int j = 1;j < tokens.length; j++) {
Station st = new Station(tokens[j]);
int n = getNum( station, tokens[j]); //得到站点编号
if( n < 0 ) { //判断站点是否存在
st.setLine(line);
station.add(st);
n = getNum( station, tokens[j]);
}
else {
if( !station.get(n).getLine().contains(line)) //判断站点是否已储存该线路
station.get(n).setLine(line);
}
int n1 = getNum( station, tokens[j-1]); //得到前后站点的编号
int n2 = -1;
if(j != tokens.length - 1) //若当前站点不为末尾,则有下一个站点的编号
n2 = getNum( station, tokens[j+1]);
if(j == 1) { //根据当前站点是首位,末尾还是其他,加入不同的边
if(n2 < 0) {
bian[n][station.size()] = 1;
bian[station.size()][n] = 1;
}
else {
bian[n][n2] = 1;
bian[n2][n] = 1;
}
}
else if(j == tokens.length - 1) {
bian[n][n1] = 1;
bian[n1][n] = 1;
}
else {
if(n2 < 0) {
bian[n][station.size()] = 1;
bian[station.size()][n] = 1;
}
else {
bian[n][n2] = 1;
bian[n2][n] = 1;
}
bian[n][n1] = 1;
bian[n1][n] = 1;
}
}
}
br.close();
}
`
提取站点编号
`
public static int getNum(ArrayList
for(int i = 0;i < station.size(); i++) { //遍历所有的站点,找到站点的编号
if(station.get(i).getName().equals( name))
return i;
}
return -1; //若不存在该站点,返回-1
}
`
输出
`
public static void shuChu(int n1,ArrayList
int l = -1;
for(int i = 0;i < station.get(n1).getLine().size(); i++)
for(int j = 0;j < station.get(lu2[0]).getLine().size(); j++)
if(station.get(n1).getLine().get(i).equals(station.get(lu2[0]).getLine().get(j))) { //判断起始的线路
System.out.println(station.get(n1).getLine().get(i)); //输出线路
for(int m = 0;m < Line.size(); m++) { //遍历得到起始线路的编号
if(Line.get(m).getName().equals(station.get(n1).getLine().get(i))) {
l = m;
break;
}
}
}
System.out.print(station.get(n1).getName() + " "); //输出站点
for(int k = 0;k < min - 1; k++) { //从第一个站点开始
System.out.print(station.get(lu2[k]).getName() + " "); //输出当前站点
int flag = 0;
for(int i = 0;i < station.get(lu2[k + 1]).getLine().size(); i++) //判断下一个站点是否在当前线路上
if(station.get(lu2[k + 1]).getLine().get(i).equals(Line.get(l).getName()))
flag = 1;
if(flag == 0) { //若没在
System.out.println();
for(int i = 0;i < station.get(lu2[k + 1]).getLine().size(); i++)
for(int j = 0;j < station.get(lu2[k + 2]).getLine().size(); j++)
if( station.get(lu2[k + 1]).getLine().get(i).equals(station.get(lu2[k + 2]).getLine().get(j))) { //根据下一站和下下站判断需要换乘的线路
System.out.println("-->" + station.get(lu2[k + 1]).getLine().get(i)); //输出换乘的线路
for(int m = 0;m < Line.size(); m++) {
if(Line.get(m).getName().equals(station.get(lu2[k + 1]).getLine().get(i))) { //更新线路编号、
l = m;
break;
}
}
}
}
}
System.out.print(station.get(lu2[min - 1]).getName() + " "); //输出终点站
}
`
Station类:描述站点的类,包含:名字name和所在的线路数组line,和对应提取数据的函数。
`
public class Station {
private String name; //站点的名字
private ArrayList<String> line = new ArrayList<String>(); //记录站点在哪几个线路
public Station(String name) {
this.name = name;
}
public void setLine(String line) {
this.line.add(line);
}
public ArrayList<String> getLine() {
return line;
}
public String getName() {
return name;
}
}
`
line类:描述线路的类,包含:线路名name和提取函数。
`
public class Line {
String name; //线路名
public Line(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
`
5、核心代码
`
public static void digist( ArrayList
if(juli <= min) { //判断此时距离是否过大
if(start == end) { //如果首尾相同,则到站
if(juli < min) {
min = juli; //改变距离最小值
for(int i = 0;i < min; i++)
lu2[i] = lu[i]; //更新当前最小路线
}
return;
}
for(int i = 0;i < 400; i++)
if(bian[start][i] == 1)
if( visit[start][i] == 0) { //判断是否走过当前路线
visit[start][i] = 1;
visit[i][start] = 1;
lu[juli] = i;
digist(station,i,end,bian,juli + 1);//迭代
visit[start][i] = 0;
visit[i][start] = 0;
}
}
}
`
6、测试用例
成功用例:

———————————————————————————————————————————————————————

如果站点不存在:



7、总结
本次的实验使用了较为简单的DSF算法进行深度遍历,结构较为简单,复杂度也较高,还有很大的提升空间。

浙公网安备 33010602011771号