地铁出行路线规划总结

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。

猜你喜欢

转载自www.cnblogs.com/anarkh/p/11672050.html