北京地铁最短路径
一、项目背景和要求
北京的地铁交通网络已经基本成型,建成的地铁线十多条,站点上百个,现需建立一个换乘指南打印系统,通过输入起点和终点站,打印出地铁换乘指南,指南内容包括起点站、换乘站、终点站。
二、功能介绍
* 地铁指定线路的查看
* 换乘指南查询
三、开发平台
* 开发语言 Java1.8
* 集成开发环境:IDEA
四、实现算法
* BFS深度优先算法
五、类职责划分
***Station 类 存放站点信息**
`public class Station {
private String StationName;/*记录站点名*/
private boolean Visited;/*是否被遍历过*/
private String PreStation;/*便于搜索是返回和记录*/
List<String> StationLine = new ArrayList<>();/*该站点存在的所有线路信息*/
List<Station> NearStation = new ArrayList<>();/*该站点存在的所有邻近站点信息*/
}`
***Line 类 存放线路信息**
`public class Line {
String LineName;/*记录当前线路名*/
ArrayList<String> Station = new ArrayList<>();/*记录该线路中所有的站点名*/
}`
[*Main 类 实现程序运转的主要功能]()
`public class Main {
static ArrayList<Line> LineList = new ArrayList<>();//存放所有线路的列表
static ArrayList<Station> StationList = new ArrayList<>();//存放线路站点的列表
static HashMap<String, Station> stationHashMap = new HashMap<>();//存放对应站点的Hash
/*对文件进行读入和存储操作*/
public static void SubwayMessage(String pathname){};
/*输出线路信息*/
public static void PrintMessage(String StartStation, String EndStation){};
}`
六、核心代码
***数据的处理**
`public static void SubwayMessage(String pathname){
try {
BufferedReader bufferedReader = new BufferedReader(new FileReader(new File(pathname)));
String NowLine = null;
while ((NowLine=bufferedReader.readLine()) != null){
Line line = new Line();
String[] StationInformation = NowLine.split(" ");
line.setLineName(StationInformation[0]);
for (int i = 1; i < StationInformation.length-1; i++){
Station NowStation = new Station();
Station NextStation = new Station();
if(stationHashMap.containsKey(StationInformation[i])){
/*如果hashmap中已经存在该站点信息,因为需要修改所以将它放入NowStation中*/
NowStation = stationHashMap.get(StationInformation[i]);
stationHashMap.remove(StationInformation[i]);
}
else{
NowStation.setStationName(StationInformation[i]);
NowStation.setVisited(false);
}
if(stationHashMap.containsKey(StationInformation[i+1])){
/*如果hashmap中已经存在该站点信息,因为需要修改所以将它放入NowStation中*/
NextStation = stationHashMap.get(StationInformation[i+1]);
stationHashMap.remove(StationInformation[i+1]);
}
else{
NextStation.setStationName(StationInformation[i+1]);
NextStation.setVisited(false);
}
/*如果站点不包含当前线路,将线路添加至站点*/
if(!NowStation.getStationLine().contains(line.LineName)){
NowStation.getStationLine().add(line.LineName);
}
if(!NextStation.getStationLine().contains(line.LineName)){
NextStation.getStationLine().add(line.LineName);
}
/*如果站点不含下一站,将相邻站添加至NextStation*/
if(!NowStation.getNearStation().contains(NextStation)){
NowStation.getNearStation().add(NextStation);
}
if(!NextStation.getNearStation().contains(NowStation)){
NextStation.getNearStation().add(NowStation);
}
NowStation.setPreStation(NowStation.getStationName());
NextStation.setPreStation(NextStation.getStationName());
stationHashMap.put(StationInformation[i], NowStation);
stationHashMap.put(StationInformation[i+1], NextStation);
/*将当前站点添加至线路中*/
if(!line.getStation().contains(NowStation.getStationName())){
line.getStation().add(NowStation.getStationName());
}
if(!line.getStation().contains(NextStation.getStationName())){
line.getStation().add(NextStation.getStationName());
}
}
LineList.add(line);
}
/*释放资源*/
bufferedReader.close();
} catch (IOException e) {
System.out.println("Read file error, Please try again!");
}
}`
***BFS广度优先搜索遍历**
`public static void SearchShortPath(String StartStation, String EndStation){
/*初始化所有站点的遍历信息*/
for (Map.Entry<String, Station> entry: stationHashMap.entrySet()){
entry.getValue().setVisited(false);
}
Queue<String> queue = new LinkedList<>();
queue.add(StartStation);
while (!queue.isEmpty()){
/*如果队列不为空,移除队列头部,将该站设置为遍历过*/
String NowStation = queue.poll();
stationHashMap.get(NowStation).setVisited(true);
if (NowStation.equals(EndStation)){
break;
}
/*对于该站点的所有相邻节点进行遍历,如果未被遍历,则PreStation设置为当前站,将该相邻站添加至队列中*/
for (Station station:stationHashMap.get(NowStation).NearStation){
if (stationHashMap.get(station.getStationName()).isVisited()==false){
stationHashMap.get(station.getStationName()).setPreStation(NowStation);
queue.add(station.getStationName());
}
}
}
}`
***输出线路信息包含换乘站**
`public static void PrintMessage(String StartStation, String EndStation){
List<String> list = new ArrayList<>();
String NowStation = EndStation;
String PreLine = "";
while (!NowStation.equals(StartStation)){
list.add(NowStation);
NowStation = stationHashMap.get(NowStation).getPreStation();
}
Collections.reverse(list);
System.out.println("当前路程共经过:"+(list.size())+"站");
System.out.print(StartStation);
for (int i = 0; i < list.size(); i++){
if(stationHashMap.get(list.get(i)).getStationLine().size()==1){
/*如果当前站点只存在一条线路,显然不可能在此站换乘*/
System.out.print("-->"+stationHashMap.get(list.get(i)).getStationName());
PreLine = stationHashMap.get(list.get(i)).getStationLine().get(0);
}
else {
/*如果该站点存在多条线路,并且下一站只有一条线路*/
if (stationHashMap.get(list.get(i+1)).getStationLine().size()==1){
/*如果该站和前一站线路相同,直接输出
* 如果不同,则表明为换乘线,输出该站名,然后显示换乘线路信息*/
if(stationHashMap.get(list.get(i+1)).getStationLine().get(0).equals(PreLine)){
System.out.print("-->"+stationHashMap.get(list.get(i)).getStationName());
}
else{
System.out.println("-->"+stationHashMap.get(list.get(i)).getStationName());
System.out.println("换乘"+stationHashMap.get(list.get(i+1)).getStationLine().get(0));
PreLine = stationHashMap.get(list.get(i+1)).getStationLine().get(0);
}
}
else{
/*对于多线路站点,如果包含前一站的线路信息说明不需要换乘
* 如果不包含,遍历前后两站的线路信息,换乘线路一定存在于两站都共有的线路节点中*/
if (stationHashMap.get(list.get(i+1)).getStationLine().contains(PreLine)){
System.out.print("-->"+stationHashMap.get(list.get(i)).getStationName());
}
else{
boolean IsSame = false;
for (int t1 = 0; t1 < stationHashMap.get(list.get(i)).getStationLine().size(); t1++){
if (stationHashMap.get(list.get(i+1)).getStationLine().contains(stationHashMap.get(list.get(i)).getStationLine().get(t1))){
System.out.println("-->"+stationHashMap.get(list.get(i)).getStationName());
System.out.println("换乘"+stationHashMap.get(list.get(i)).getStationLine().get(t1));
PreLine = stationHashMap.get(list.get(i)).getStationLine().get(t1);
IsSame = true;
break;
}
}
if(IsSame){
System.out.print("-->"+stationHashMap.get(list.get(i)).getStationName());
}
}
}
}
}
}`
***查找线路信息**
`public static void SearchLine(String LineName){
List<String> Line = new ArrayList<>();
boolean IsSearch =false;
for(Line line: LineList){
if (line.getLineName().equals(LineName)){
IsSearch = true;
System.out.println("当前线路为"+LineName);
for (int i = 0; i < line.getStation().size(); i++){
if (i == 0){
System.out.print(line.getStation().get(i));
}else{
System.out.print("-->"+line.getStation().get(i));
}
}
break;
}
}
if(IsSearch == false){
System.out.println("未找到该线路");
}
}`
七、测试用例
*同一线路的站点之间的最短路径

*不同线路之间站点的最短路径

*查询线路信息

*查询不存在的站点

*查询不存在的线路

八、项目总结
*自己的代码能力还是存在不足,最开始读入数据阶段,没有采用正确的数据结构,从而导致了最后的BFS的算法报错
*通过地铁项目,将实际问题放入计算机中进行项目的编写让我了解到了项目从无到有的一个过程
九、该项目所有代码均已上传至Github,具体网站如下:
https://github.com/13588386674/BeijingSubway