北京地铁线路规划系统
北京地铁线路规划系统
项目概况
本次项目是以邻接表的形式来存储图,通过Folyd算法算出任意两点之间的路线图并以数字的形式来代替站点名称存储在dist1.txt文件中并保存在本地。等用户通过输入各种命令,再从本地读入subway.txt文件或者dist1.txt文件进行相应输出。
java图实现
- 首先创建Vertex类(存储每个点的信息)
private String verName;
private Vertex nextNode = null;
private int verId;
private Set<Integer> TNumber = new HashSet<Integer>();
verName表示站点名称
nextNode表示邻接表中相邻的一个顶点
verId表示把站点名称转换成对应的Id号
TNumber表示该站点可以换成的地铁编号
- Graph类用于保存每个顶点信息
private static Vertex[] vertexArray = new Vertex[330];
private int verNum = 0;
这里创建的是一个静态Vertex[]数组,用来创建一个单例模式vertexArray
verNum表示站点数量
这个类中最重要的是这两个方法,方便等下在读取subway.txt文件创建Vertex时防止重复,更重要的是为了通过VertexID或者VertexName来获取站点信息。
public Vertex getVertexByName(String verName,int count) {
for(int i= 0 ; i < count; i++) {
if(vertexArray[i].getVerName().equals(verName)) {
return vertexArray[i];
}
}
return null;
}
public Vertex getVertexById(int verId,int count) {
for(int i= 0 ; i < count; i++) {
Vertex v = vertexArray[i];
if(vertexArray[i].getVerId() == verId) {
return vertexArray[i];
}
}
return null;
}
具体实现
计算任意两点之间的最短线路
邻接表建立
设置一个计数器count来保存有多少个站点,当然,在遍历读取subway.txt文件时,便把count来当做每个站点的Id并保存在Vertex信息中。
把subway.txt文件中每一行通过空格来划成字符串数组chars
,并通过每个字符串是否有\’#\’来保存每个站点的换乘信息,通过\’:\’来保存当前是几号线路并赋给TNumber,每个站点创建的信息保存主要如下。
vertex = new Vertex();
vertex.setVerName(chars[i]);
vertex.setVerId(count);
vertex.getTNumber().add(TNumber)
Graph.getVertexArray()[count] = vertex;
通过再次遍历文件信息,来用邻接表连接相邻站点。
主要是通过
Vertex v1 = Graph.getVertexByName(lastVertex.getVerName(), count);
Vertex v2 = new Vertex();
v2.setVerName(chars[i]);
v2.setNextNode(vertex1.getNextNode());
v1.setNextNode(vertex2);
Vertex reV2 = graph.getVertexByName(chars[i] , count);
Vertex reV1 = new Vertex();
reV1.setVerName(lastVertex.getVerName());
reV1.setNextNode(reV2.getNextNode());
reV2.setNextNode(reV1);
lastVertex = vertex2;
每个站点的邻接表中只存储相邻站点的名称,并不存储其他信息,这样通过上述代码就建立了一个无向的邻接表。
通过Floyd算法计算任意两点之间的路径
private static ArrayList<Integer>[][] arr = (ArrayList<Integer>[][]) new ArrayList[300][300];
通过以上代码创建一个ArrayList二维数组,实则是创建了一个第三维度可变的三维数组。
dist数组来保存任意两点之间的距离,首先都赋初值为400(因为站点的个数小于300,所以以400表示两只之间不可达),之后把邻接表中存储的相邻站点的距离赋为1
之后是几行经典的Floyd代码
for(int k=0; k<count; k++) {
for(int i=0; i<count; i++) {
for(int j=0; j<count; j++) {
if(dist[i][j] > (dist[i][k]+dist[k][j])) {
dist[i][j] = dist[i][k]+dist[k][j];
arr[i][j].clear();
arr[i][j].add(k);
}
}
}
}
并通过Output函数输出任意两点之间的站点信息到dist1.txt文件中
private static void Output(int i, int j,BufferedWriter writer) {
if(arr[i][j].size() == 0) {
return;
}
else {
for(int k=0; k<arr[i][j].size(); k++) {
Output(i,arr[i][j].get(k),writer);
try {
writer.write(" "+arr[i][j].get(k));
} catch (IOException e) {
e.printStackTrace();
}
Output(arr[i][j].get(k),j,writer);
}
}
}
用户测试
首先是要读入vertex.txt文件中的信息(里面主要存储了每个站点的中文名称,数字Id,可换成线路数字Id)和SNumber.txt文件中的信息(主要保存每条线路中文名称和相应数字Id)
SNumber.txt文件中有如下信息:
线路中文名称 | ID |
---|---|
地铁1号线 | 1 |
地铁2号线 | 2 |
地铁4号线 | 4 |
地铁5号线 | 5 |
地铁6号线 | 6 |
地铁7号线 | 7 |
地铁8号线 | 8 |
地铁9号线 | 9 |
地铁10号线 | 10 |
地铁13号线 | 13 |
地铁14号线东段线 | 141 |
地铁14号线西段线 | 142 |
地铁15号线 | 15 |
地铁八通线 | 3 |
地铁昌平线 | 11 |
地铁亦庄线 | 12 |
地铁房山线 | 16 |
地铁机场线 | 17 |
而vertex.txt中内容格式如下
公主坟 7 1 10
其中0表示公主坟对应的Id为7 ; 1和10表示公主坟所在为1号线和10号线(也就是公主坟可换成1号线或10号线)
读取完对应信息后需要通过用户输入参数输出对应信息
-
用户根据-map参数来获得所有北京地铁线路信息
-
用户通过-a+地铁几号线参数来获得某条线路经过的所有站点信息,并通过命令参数-o进行输出
-
用户通过-b+起始站点名称+终止站点名称参数来获得一条线路来从指定出发点到达目的地(这条线路要求经过最少的站数)
-
两个站点均为普通站点
-
起点为转站站点,终点为普通站点
-
起点为普通站点,终点为转站站点
-
起点和终点均为转站站点
-
-
健壮性演示
-
参数错误
-
线路不存在
-
站点不存在
-
输入相同站点
-
总结
本次项目让我深刻理解了在java中如何创建图,并回顾了Floyd算法求出最短路径,
但是最主要的收获就是只有自己亲自实践才发现一些东西再写的时候与脑中一开始预想的截然不同,
比如我一开始还在想怎么确定哪两个点之间是相邻的,因为有换成线路的存在,
但是再写的时候其实就发现就只是遍历一遍数据其实就行了,甚至如果不需要输出换乘信息,
那么换乘信息也不需要保存在文件中