github地址:https://github.com/anarkhwqh/Subway
数据处理
将各地铁路线的路线名及站点名放入txt文件中,若这是一条环形线路,则起始站和终点站为同一站,格式如下:
1号线 苹果园 古城 八角游乐园········四惠 四惠东
2号线 西直门 积水潭 鼓楼大街········车公庄 西直门
·
·
·
S1线 石厂 小园 栗园庄············ 四道桥 金安桥
读取文件函数为
public void loadSubwayFile(String subway_file) {
BufferedReader reader = null;
File subway = new File(subway_file);
try {
reader = new BufferedReader(new FileReader(subway));
String t = null;
while ((t = reader.readLine()) != null) {
List<String> line = Arrays.asList(t.split(" "));
station.add(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
每一条地铁线为一行,将每一行转化为数组再保存为List,保存入 List<List<String>>
station 中,通过 Map<String, Integer> name_num
对每个地铁站进行编号
public void mapping() {
int cnt = 1;
for (List<String> line : station) {
//因为下标为0的都为线路名称,所以i从1开始
for (int i = 1; i < line.size(); i++) {
if (!name_num.containsKey(line.get(i))) {
num_name.put(cnt, line.get(i));
name_num.put(line.get(i), cnt++);
}
}
}
}
根据编号的cnt可知,共有332个地铁站
Dijkstra规划路线
Dijkstra
private static int[][] c = new int[500][500];
//存储地铁站连通情况,c[i][j]等于1表示两站相邻,等于0表示不相邻
private static int[] prev = new int[500];
//存储最短路径
private static int[] dist = new int[500];
//存储最短距离
private static boolean[] s = new boolean[500];
//记录某点是否遍历过
private static int n = 332;
//总站点数
void Dijkstra(int v) {
Arrays.fill(s, false);
Arrays.fill(prev, 0);
for (int i = 1; i <= n; i++) {
dist[i] = c[v][i];
if (dist[i] != 999999)
prev[i] = v;
}
dist[v] = 0;
s[v] = true;
for (int i = 2; i <= n; i++) {
int tmp = 999999;
int u = v;
for (int j = 1; j <= n; j++) {
if ((!s[j]) && dist[j] < tmp) {
u = j;
tmp = dist[j];
}
}
s[u] = true;
for (int j = 1; j <= n; j++) {
if (dist[u] + c[u][j] < dist[j]) {
dist[j] = dist[u] + c[u][j];
prev[j] = u;
} else if (dist[u] + c[u][j] == dist[j]) {
int a = searchPath(v, u);
int b = searchPath(v, prev[j]);
if (u != j && a < b) {
if (a < b)
prev[j] = u;
else {
for (List<String> line : station) {
if (line.contains(num_name.get(u)) && line.contains(num_name.get(j)))
prev[j] = u;
}
}
}
}
}
}
}
在上面的mapping()
函数中对c[][]
进行初始化
for (int i = 1; i < line.size(); i++) {
if (i != 1) {
int a = name_num.get(line.get(i));
int b = name_num.get(line.get(i - 1));
c[a][b] = c[b][a] = 1;
}
}
searchPath
int searchPath(int v, int u) {
int[] que = new int[500];
int cnt = 0;//换乘次数
int tot = 1;
que[tot] = u;
tot++;
int tmp = prev[u];
while (tmp != v) {
que[tot] = tmp;
tot++;
tmp = prev[tmp];
}
que[tot] = v;
for (int i = tot; i >= 1; i--) {
boolean f = false;
if (i == tot)
f = true;
else if (i != 1) {
for (List<String> line : station) {
if (line.contains(num_name.get(que[i + 1])) && line.contains(num_name.get(que[i - 1]))) {
f = true;
break;
}
}
}
if (i != 1 && !f) {
cnt++;
}
}
return cnt;
}
UI界面
没有采用网页或app的形式,直接在java中写的UI,比较简陋,界面如下
样例测试
- 比较长的路线
- 有重叠的路线
- 输入的起点或终点错误
- 起点和终点是同一个
扫描二维码关注公众号,回复:
7464260 查看本文章
#不足之处及总结
地铁图是一张稀疏图,而迪杰斯特拉算法更适合于稠密图,但是由于地铁点较少,所以运行速度也比较快。其次是在可视化方面,本身想尝试做做看类似于在地铁站购票时的页面,点击某一块区域,然后那块区域放大,在选择相应的地铁站,也可以拖动地图,但是没有实现。还有一个一直没有解决的问题,用Java编写UI界面时,放入一张图片调整到合适的大小后总是失真非常严重,不知道该怎么解决。最后,对于这次个人作业,效率不高,开头很拖沓,很多时候的bug都是一些细节问题,在编写代码的过程中思虑不够周全,导致后面花长时间来调bug。