一 问题重述
1.实现地铁线路的加载
2.实现查询指定线路所有站点(包括换乘信息)
3.实现查询指定两个站点间的最短路径
二 功能设计
1.实现地铁线路的加载
-map subway.txt //将存储在subway.txt文件里的地铁线路进行读取
2.实现查询指定线路所有站点
-a 地铁线路名称 -map subway.txt -o station.txt //读取subway.txt文件信息后,通过输入的地铁线路名称,将指定地铁线路的所有站点写入station.txt文件
3.实现查询指定两个站点间的最短路径
-b 起始站点 目的站点 -map subway.txt -o routine.txt //读取subway.txt文件信息后,通过输入的起始站点和目的站点,将最短路径的所有站点写入routine.txt文件
三 项目内容
1.文本地图存储方式
地铁线路名称
站点1 站点2[其它途经地铁线1][其它途经地铁线2……] …… 站点n
以地铁1号线为例
1号线
苹果园 古城 八角游乐园 八宝山 玉泉路 五棵松 万寿路 公主坟[10号线] 军事博物馆[9号线] 木樨地 南礼士路 复兴门[2号线] 西单[4号线] 天安门西 天安门东 王府井 东单[5号线] 建国门[2号线] 永安里 国贸[10号线] 大望路[14号线东段] 四惠[八通线] 四惠东[八通线]
注意:地铁站名使用中文字符以外,其它所有字符均采用英文半角字符。站点信息中也应不存在空格符,比如 公主坟[ 10号线]
2.文本与程序数据转换
class SubwayLine
{
public String Name;
public List<String> InLineSubwayStationsName;
}
class Station
{
public String Name;
public boolean IsTransferStation ;
public List<String> PlacedSubwayLineName;
}
这里以两行为一个单位进行读取,能够读取地铁线路名称及对应的所有站点信息
while ((lineTxt = br.readLine()) != null) {//首先读取第一行的地铁线路名称 sl.setName(lineTxt);
if((lineTxt = br.readLine()) != null) {//然后读取第二行站点信息 stations=lineTxt.split(" "); //对第二行站点信息进行以空格切分,并且存入String[]stations subwaystations=new ArrayList<>(stations.length); List<String> updatesubwaystations=new ArrayList<>(stations.length);
Collections.addAll(subwaystations, stations);
然后用正则表达式对每个站点的信息进行提取,存入SubwayLine
结构,然后合并所有SubwayLine
为一个Hashtable SubwayLines
的排序列表。结合所有路线信息,创建另一个排序列表List<String> subwaystationnames 实现站点名与邻接矩阵下标的对应关系,不会创建重复的站点名键
3.创建邻接矩阵(UDG)
public MatrixUDG(List<String> vexs, ArrayList<ArrayList<String>> edges) {//vexs为地铁所有站名集合,edges为二维数组存放每个站点所处所有线路的相邻站点信息
// 初始化"顶点数"和"边数"
int vlen = vexs.size();
int elen = edges.size();
// 初始化"顶点"
mVexs = new ArrayList<String>();
mVexs.addAll(vexs);
// 初始化邻接矩阵
mMatrix=new int[vlen][vlen];
for(int i=0;i<vlen;i++) {
for(int j=0;j<vlen;j++)
mMatrix[i][j] =INF;
}
for (int i = 0; i < elen; i++) {
// 读取边的起始顶点和结束顶点
int p1 = getPosition(edges.get(i).get(0));
int p2 = getPosition(edges.get(i).get(1));
mMatrix[p1][p2] = 1;
mMatrix[p2][p1] = 1;
}
}
4.Floyd算法(求多源最短路径)
public void floyd(int[][] matrix){//通过已经建立的mMatrix矩阵,进行floyd算法计算
int size=matrix.length;
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
path[i][j]=-1;
dist[i][j]=matrix[i][j];
}
}
for(int k=0;k<size;k++){
for(int i=0;i<size;i++){
for(int j=0;j<size;j++){
if(dist[i][k]!=INF&&
dist[k][j]!=INF&&
dist[i][k]+dist[k][j]<dist[i][j]){//dist[i][k]+dist[k][j]>dist[i][j]-->longestPath
dist[i][j]=dist[i][k]+dist[k][j];
path[i][j]=k;
}
}
}
}
}
采用Floyd最短路径算法进行计算,这个方法较为简单,一次计算所有的路径后存储于矩阵中,采用了递归的方式,不断在两点之间寻找最短中转点,直到两个点为相邻点,这样就可以通过Floyd路径矩阵找到完整的路径
5.测试
-map BJsubway.txt ----->成功读取subway.txt文件
-a 1号线 -map BJsubway.txt -o station.txt ----->已将结果写入station.txt文件
station.txt内容
苹果园
古城
八角游乐园
八宝山
玉泉路
五棵松
万寿路
公主坟
军事博物馆
木樨地
南礼士路
复兴门
西单
天安门西
天安门东
王府井
东单
建国门
永安里
国贸
大望路
四惠
四惠东
-b 大井 动物园 -map BJsubway.txt -o routine.txt ----->已将结果写入routine. txt文件
routine.txt内容
共计9个站点
大井
七里庄
六里桥东
北京西站
军事博物馆
白堆子
白石桥南
国家图书馆
动物园
四 项目总结学习
本次个人项目共花费四天时间,虽然还有细节未完成
第一天计划并完成文本地图的存储和文本数据与程序的转化,对先前的地铁线路信息的存储格式进行修改,通过查询构建新的存储结构,之后在数据与程序的转化上,粗浅学习了正则表达式
第二天计划并完成无向图的邻接矩阵的创建,将vexs地铁站点名称集合和edges各站点相邻信息输入,得到以INF,1分布的邻接矩阵(mMatrix[i][j]==1表示站点i与站点相邻,INF表示无邻边)
第三天计划并完成Floyd算法实现两点最短路径,学习和比较了Floyd算法和Dijksta算法,Floyd算法的path[][]矩阵的更新比较难理解,将构建的邻接矩阵作为输入,得到两点的最短路径
第四天整理和完成代码修正,文档博客编写
整个项目完成下来,头是真的大,各种细小的东西都得自己研究,比如:各种类型之间的转换,subwaylines该用什么结构进行存储,List<String>的内容如何存入txt文件,如何将Object对象存入txt文件等等,总的来说,这次的个人项目对自己帮助挺大的,感觉学会了独立生存,别人的建议只能是咨询,自己的想法才是关键
Github地址:https://github.com/Kuzzri/JavSubway