地铁线路最短路径

主要内容:
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 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<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 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  林世宇  阅读(173)  评论(1)    收藏  举报