@[toc]
项目GitHub地址
https://github.com/yonginggg/BeijingSubwayTransfer
文件存放 station.txt
1号线 苹果园 古城 八角游乐园 八宝山 玉泉路 五棵松 万寿路 公主坟 军事博物馆 木樨地 南礼士路 复兴门 西单 天安门西 天安门东 王府井 东单 建国门 永安里 国贸 大望路 四惠 四惠东
2号线 西直门 车公庄 阜成门 复兴门 长椿街 宣武门 和平门 前门 崇文门 北京站 建国门 朝阳门 东四十条 东直门 雍和宫 安定门 鼓楼大街 积水潭 西直门
3号线 天宫院 生物医药基地 义和庄 黄村火车站 黄村西大街 清源路 枣园 高米店南 高米店北 西红门 新宫 公益西桥 角门西 马家堡 北京南站 陶然亭 菜市口 宣武门 西单 灵境胡同 西四 平安里 新街口 西直门 动物园 国家图书馆 魏公村 人民大学 海淀黄庄 中关村 北京大学东门 圆明园 西苑 北宫门 安河桥北
5号线 宋家庄 刘家窑 蒲黄榆 天坛东门 磁器口 崇文门 东单 灯市口 东四 张自忠路 北新桥 雍和宫 和平里北街 和平西桥 惠新西街南口 惠新西街北口 大屯桥东 北苑路北 立水桥南 立水桥 天通苑南 天通苑 天通苑
6号线 金安桥 杨庄 西黄村 廖公庄 田村 海淀五路居 慈寿寺 花园桥 白石桥南 车公庄西 车公庄 平安里 北海北 南锣鼓巷 东四 朝阳门 东大桥 呼家楼 金台路 十里堡 青年路 褡裢坡 黄渠 常营 草房 物资学院路 通州北关 通运门 北运河西 北运河东 郝家府 东夏园 潞城
7号线 北京西站 湾子 达官营 广安门内 菜市口 虎坊桥 珠市口 桥湾 磁器口 广渠门内 广渠门外 九龙山 大郊亭 百子湾 化工 南楼梓庄 欢乐谷景区 垡头 双合 焦化厂
8号线 朱辛庄 育知路 平西府 回龙观东大街 霍营 育新 西小口 永泰庄 林萃桥 森林公园南门 奥林匹克公园 奥体中心 北土城 安华桥 安德里北街 鼓楼大街 什刹海 南锣鼓巷 中国美术馆
8号线南段 珠市口 天桥 永定门外 木樨园 海户屯 大红门南 和义 东高地 火箭万源 五福堂 德茂 瀛海
9号线 国家图书馆 白石桥南 白堆子 军事博物馆 北京西站 六里桥东 六里桥 七里庄 丰台东大街 丰台南路 科怡路 丰台科技园 郭公庄
10号线 劲松 双井 国贸 金台夕照 呼家楼 团结湖 农业展览馆 亮马桥 三元桥 太阳宫 芍药居 惠新西街南口 安贞门 北土城 健德门 牡丹园 西土城 知春路 知春里 海淀黄庄 苏州街 巴沟 火器营 长春桥 车道沟 慈寿寺 西钓鱼台 公主坟 莲花桥 六里桥 西局 泥洼 丰台站 首经贸 纪家庙 草桥 角门西 角门东 大红门 石榴庄 宋家庄 成寿寺 分钟寺 十里河 潘家园 劲松
新机场线 草桥 大兴新城 大兴机场
13号线 西直门 大钟寺 知春路 五道口 上地 西二旗 龙泽 回龙观 霍营 立水桥 北苑 望京西 芍药居 光熙门 柳芳 东直门
14号线西端 张郭庄 园博园 大瓦窑 郭庄子 打井 七里庄 西局
14号线东端 北京南站 永定门外 景泰 蒲黄榆 方庄 十里河 北工大西门 平乐园 九龙山 大望路 金台路 朝阳公园 枣营 东风北桥 将台 望京南 阜通 望京 东湖渠 来广营 善各庄
15号线 俸伯 顺义 石门 南法信 后沙峪 花梨坎 国展 孙河 马泉营 崔各庄 望京东 望京 望京西 关庄 大屯路东 安立路 奥林匹克公园 北沙滩 六道口 清华东路西口
16号线 北安河 温阳路 稻香湖路 屯佃 永丰 永丰南 西北旺 马连洼 农大南路 西苑
八通线 四惠 四惠东 高碑店 传媒大学 双桥 管庄 八里桥 通州北苑 果园 九棵树 梨园 临河里 土桥
昌平线 昌平西山口 十三陵景区 昌平 昌平关东 北邵洼 南邵 沙河高教园 沙河 巩华城 朱辛庄 生命科学园 西二旗
亦庄线 宋家庄 肖村 小红门 旧宫 亦庄桥 亦庄文化园 万源街 荣京东街 荣昌东街 同济南路 经海路 次渠南 次渠 亦庄火车站
房山线 郭公庄 大葆台 稻田 长阳 篱笆房 广阳城 良乡大学城北 良乡大学城 良乡大学城西 良乡南关 苏庄 阎村东
机场线 东直门 三元桥 T2航站楼 T3航站楼
s1号线 金安桥 四道桥 桥户营 上岸 栗园庄 小园 石厂
燕房线 燕山 房山城关 饶乐府 马各庄 大石河东 星城 阎村 紫草坞 阎村东
西郊线 香山 植物园 万安 茶棚 颐和园西门 巴沟
设计思路与模块分析
Station.java
定义了站点Station的类结构和图的结构
import java.util.HashMap;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
public class Station {
private String name; //地铁站名称
public Station prev; //前一个站
public Station next; //后一个站
//本站到某一个目标站(key)所经过的所有站集合(value),保持前后顺序
private Map> orderSetMap = new HashMap>();
public Station(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public LinkedHashSet getAllPassedStations(Station station) {
if (orderSetMap.get(station) == null) {
LinkedHashSet set = new LinkedHashSet();
set.add(this);
orderSetMap.put(station, set);
}
return orderSetMap.get(station);
}
public Map> getOrderSetMap() {
return orderSetMap;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (obj instanceof Station) {
Station s = (Station) obj;
if (s.getName().equals(this.getName())) {
return true;
} else {
return false;
}
} else {
return false;
}
}
@Override
public int hashCode() {
return this.getName().hashCode();
}
}
DataBuilder.java
读取文件,创建地铁路线(得到的是去除了第一列后的站点的集合以及总的站点的数量 得到的站点信息以HashSet> lineSet的形式保存, 每一个list保存的是其中一条线路的信息
import java.util.*;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.Thread.State;
public class DataBuilder {
public static HashSet> lineSet = new HashSet>();//所有线集合
public static int totalStaion = 0;//总的站点数量
//读取文件
public static void readFile() throws IOException{
FileInputStream inputStream = new FileInputStream("D:\\Work\\北京地铁\\src\\station.txt");
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String str = null;
while((str = bufferedReader.readLine()) != null)
{
List line = new ArrayList();
String[] lineInformations = str.split(" ");
for(String s : lineInformations){
line.add(new Station(s));
}
line.remove(0);
for(int i =0;i
StationIncludeLineName.java
读取文件,创建地铁路线(得到的是没有去除了第一列后的set
import java.util.*;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
public class StationIncludeLineName {
public static HashSet> lineSet = new HashSet>();//所有线集合
public static int totalStaion = 0;//总的站点数量
//读取文件
public static void readFile(String fileName) throws IOException{
FileInputStream inputStream = new FileInputStream(fileName);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String str = null;
while((str = bufferedReader.readLine()) != null)
{
List line = new ArrayList();
String[] lineInformations = str.split(" ");
for(String s : lineInformations){
line.add(new Station(s));
}
for(int i =0;i
Subway.java
先创建一个outLIst存放读取过的站点的信息; 一个allStation用来保存得到的最短路径经过的站点名字,用来进行文件的生成操作
private List outList = new ArrayList();
String allStations = "";
计算从s1站到s2站的最短经过路径, 并输出文件
遍历所有的线路信息,并将遍历过的station添加到List< Station> outList中, 当outList.size() == DataBuilder.totalStaion即全部遍历后, 使用Station station : s1.getAllPassedStations(s2)得到s1到s2的路线并将名字保存到allStations
public String calculate(Station s1, Station s2) {
//长度相等级找完了全部的路径,输出文件
if (outList.size() == DataBuilder.totalStaion) {
allStations+="找到目标站点:" + s2.getName() + ",共经过" + (s1.getAllPassedStations(s2).size() - 1) + "站"+"\n";
for (Station station : s1.getAllPassedStations(s2)) {
allStations+=station.getName() + "->";
}
return allStations;
}
if (!outList.contains(s1)) {
outList.add(s1);
}
//如果起点站的OrderSetMap为空,则第一次用起点站的前后站点初始化
if (s1.getOrderSetMap().isEmpty()) {
List Linkedstations = getAllLinkedStations(s1);
for (Station s : Linkedstations) {
s1.getAllPassedStations(s).add(s);
}
}
Station parent = getShortestPath(s1);//获取距离起点站s1最近的一个站
if (parent == s2) {
allStations+="找到目标站点:" + s2 + ",共经过" + (s1.getAllPassedStations(s2).size() - 1) + "站"+"\n";
for (Station station : s1.getAllPassedStations(s2)) {
allStations+=station.getName() + "->";
}
return allStations;
}
for (Station child : getAllLinkedStations(parent)) {
if (outList.contains(child)) {
continue;
}
int shortestPath = (s1.getAllPassedStations(parent).size() - 1) + 1;//前面这个1表示计算路径需要去除自身站点,后面这个1表示增加了1站距离
if (s1.getAllPassedStations(child).contains(child)) {
//如果s1已经计算过到此child的经过距离,那么比较出最小的距离
if ((s1.getAllPassedStations(child).size() - 1) > shortestPath) {
//重置S1到周围各站的最小路径
s1.getAllPassedStations(child).clear();
s1.getAllPassedStations(child).addAll(s1.getAllPassedStations(parent));
s1.getAllPassedStations(child).add(child);
}
} else {
//如果s1还没有计算过到此child的经过距离
s1.getAllPassedStations(child).addAll(s1.getAllPassedStations(parent));
s1.getAllPassedStations(child).add(child);
}
}
outList.add(parent);
calculate(s1, s2);//重复计算,往外面站点扩展
return allStations;
}
获得station到各个站的最短距离
定义一个MAX_VALUE, 然后使用getAllPassedStations的方法来得到station到s所经过的所有站点的集合,返回它的size即距离
private Station getShortestPath(Station station) {
int minPatn = Integer.MAX_VALUE;
Station rets = null;
for (Station s : station.getOrderSetMap().keySet()) {
if (outList.contains(s)) {
continue;
}
LinkedHashSet set = station.getAllPassedStations(s);//参数station到s所经过的所有站点的集合
if (set.size() < minPatn) {
minPatn = set.size();
rets = s;
}
}
return rets;
}
得到所求的Station所在路线的所有站点
循环遍历从文件中读取到的所有线路信息, 如果所求的Station包含在该线路中, 将这一线路返回
private List getAllLinkedStations(Station station) {
List linkedStaions = new ArrayList();
for (List line : DataBuilder.lineSet) {
if (line.contains(station)) {//如果某一条线包含了此站
Station s = line.get(line.indexOf(station));
if (s.prev != null) {
linkedStaions.add(s.prev);
}
if (s.next != null) {
linkedStaions.add(s.next);
}
}
}
return linkedStaions;
}
文件写入
public static void writeFileString(String strings, String writeFileName) {
File fileDir = new File(writeFileName);
if(!fileDir.isFile()){
try {
fileDir.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
FileWriter fw = new FileWriter(fileDir);
fw.write(strings);
fw.flush();
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
主函数. 使用参数化运行的方法
使用正则表达式去匹配
public static void main(String[] args) throws IOException {
String map = "-map \\S+ ";
String line = "-a \\S+ -map \\S+ -o \\S+ ";
String path = "-b \\S+ \\S+ -map \\S+ -o \\S+ ";
String arge = "";
for (String i : args) {
arge += i + " ";
}
if (arge.matches(map)) {
String readFile = args[1];
StationIncludeLineName.readFile(readFile);
for (List linename : StationIncludeLineName.lineSet) {
for (int i = 0; i < linename.size(); i++) {
System.out.print(linename.get(i).getName() + "-->");
}
System.out.println();
}
} else if (arge.matches(line)) {
String lineName = args[1];
String readFile = args[3];
String writeFile = args[5];
StationIncludeLineName.readFile(readFile);
Station station = new Station(lineName);
String allStations = "";
int flag = 0;//判断是否存在该路线
for (List linename : StationIncludeLineName.lineSet) {
if (linename.contains(station)) {
allStations+=linename.get(0).getName() + "包括的站点:"+"\n";
for (int i = 1; i < linename.size(); i++) {
allStations+=linename.get(i).getName() + "-->";
}
flag=1;
}
}
if(flag==0){
System.out.println("该路线不存在");
}
else{
writeFileString(allStations, writeFile);
}
} else if (arge.matches(path)) {
String start = args[1];
String end = args[2];
String readFile = args[4];
String writeFile = args[6];
DataBuilder.readFile(readFile);
Subway sw = new Subway();
String allStations = sw.calculate(new Station(start), new Station(end));
// System.out.println(allStations);
writeFileString(allStations, writeFile);
}else{
System.out.println("输入参数有误");
}
}
测试
需求1
程序启动时需要通过读取 -map 参数来获得对应的自定义地铁文件(命名为 subway.txt),从而得到地铁线路图的信息。
java subway -map subway.txt
需求2
在给定地铁线路时,你的程序就需要能够从线路的起始站点开始,依次输出该地铁线经过的所有站点,直到终点站
java subway -a 1号线 -map subway.txt -o station.txt
需求3
给出起点和终点, 保存路径信息到文件中
subway.exe -b 香山 焦化厂 -map subway.txt -o routine.txt