地铁线路最短路径

主要内容:
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 = new ArrayList(); //站点集合
int[][] bian = new int[400][400]; //边
ArrayList line = new ArrayList(); //线路集合

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 station,int[][] bian, ArrayList Line) throws IOException {

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 station, String name) {

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 station, ArrayList Line) {

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 line = new ArrayList(); //记录站点在哪几个线路

public Station(String name) {
this.name = name;
}

public void setLine(String line) {
this.line.add(line);
}

public ArrayList 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 station, int start, int end, int[][] bian,int juli) {

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算法进行深度遍历,结构较为简单,复杂度也较高,还有很大的提升空间。

posted @ 2020-11-04 21:42  林世宇  阅读(184)  评论(1)    收藏  举报