2019软件工程——地铁个人项目总结
时间:2019-10-15
本文章向大家介绍2019软件工程——地铁个人项目总结,主要包括2019软件工程——地铁个人项目总结使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
GitHub
项目要求
实现类似百度地图等应用的公共交通换乘查询功能,要求为北京地铁换乘
开发环境
Windows10操作系统,java version "1.8.0_221",开发工具eclipse
项目效果预览
Java类表
类 | 说明 |
metroUtil | 项目入口 |
ReaderTxt | 将含有站点和线路信息的.txt文件读取并存入数据结构 |
Station | 地铁站类 |
Subway | Java UI地铁系统,将数据结构转化为图 |
Dijkstra | 迪杰斯特拉算法寻找合理的换乘方案 |
.txt文件格式
从左至右依次为线路编号,站点名称,所属线路,开通状态,是否换乘站。文件中某站点上下相邻站点若属于同一地铁线,则默认现实中互为相邻站点。
程序流程
算法思想
地铁线路换乘查询其本质上为图的最短路径问题,在本项目中可以理解为寻找无向图起始节点与目的节点之间的最短路径,并记录路径输出在UI中。
1:有效数据读取,即读取开通的站点及其所属线路,存储为类ReaderTxt 的静态属性Map<String, List<Station>> map。
void readFileContent(String fileName)
reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8")); String tempStr = null; int staId = 0;//站点编号,唯一 int time = 0; while ((tempStr = reader.readLine()) != null) {// 判断是否读到文件末尾 if (time == 0) {// 如果读取的是第一条数据则初始化站点列表对象 time++; line_stations = new LinkedList<>(); } String[] message = tempStr.split("\\s+");// 分割站点信息 lines.add(message[2]);// 读地铁线路 if (message[3].equals("1")) {// 读取开通的地铁站 // 读取同一条线路的站点,读完则更新map并重新创建新线路的站点列表 if (!allStations.isEmpty() && !((Station) ((LinkedList) allStations).getLast()).getLine().equals(message[2])) { map.put(((Station) ((LinkedList) allStations).getLast()).getLine(), line_stations); line_stations = new LinkedList<>(); } Station station = new Station(staId++, message[1], message[2], message[4].equals("1")); allStations.add(station); line_stations.add(station); } } reader.close();
2:数据预处理,考虑北京地铁线路存在环线的特殊情况,即起始站点和终点站为同一站点,则需要将原来存储在map中的数据信息去重,同时更新站点编号(唯一),存储所有站点信息到List<Station> allStations ,初始化int型矩阵graph用于存储站点间的连通情况
void initialize()
具体实现见Github
3:换乘查询,其核心算法为迪杰斯特拉算法,由Dijkstra类实现
Dijkstra类属性
/* 属性 */ private Queue visited = null;// 已访问站点 int[] distance = null;;// 路径长度 private Map<String, List<Station>> line_stations = null; static String nowLine = null;// 当前地铁线 static String[] nextLine = null;// 当前节点的下一换乘地铁线 static HashMap path = null;// 路径 static List<Station> list = null;
初始化路径长度数组distance
// 路径HashMap path; path = new HashMap(); for (int i = 0; i < list.size(); i++) path.put(i, ""); // 初始化路径长度数组distance for (int i = 0; i < list.size(); i++) { path.put(i, path.get(i) + "" + list.get(v).getStaName()); if (i == v) distance[i] = 0; // 连通站点 else if (weight[v][i] != -1) { distance[i] = weight[v][i]; // 获取当前站点所属的地铁线 nowLine = list.get(v).getLine(); StringBuffer sbf = new StringBuffer(); for (Station s : line_stations.get(nowLine)) { sbf.append(s.getStaName()); } // 起点站和下一站点是否属于同一地铁线 if (sbf.indexOf(list.get(i).getStaName()) != -1) { path.put(i, path.get(i) + "\n\t-->" + list.get(i).getStaName()); nextLine[i] = nowLine; } else { path.put(i, path.get(i) + "\n-->换乘" + list.get(i).getLine() + "\n\t-->" + list.get(i).getStaName()); nextLine[i] = list.get(i).getLine(); } } // 不连通 else distance[i] = Integer.MAX_VALUE; }
visited.add(v);
迭代寻找最优路径
//迭代寻找最优线路 while (visited.size() < list.size()) { int k = getIndex(visited, distance);// 获取未访问点中距离源点最近的点 visited.add(k); if (k != -1) { for (int j = 0; j < list.size(); j++) { if (weight[k][j] != -1)// 判断k点能够直接到达的点 { // 通过遍历各点,比较是否有比当前更短的路径,有的话,则更新distance,并更新path。 if (distance[j] > distance[k] + weight[k][j]) { distance[j] = distance[k] + weight[k][j]; nowLine = nextLine[k]; StringBuffer sbf = new StringBuffer(); for (Station s : line_stations.get(nowLine)) { sbf.append(s.getStaName()); } //判断到下一站点是否需要换乘 if (sbf.indexOf(list.get(j).getStaName()) != -1) { path.put(j, path.get(k) + "\n\t-->" + list.get(j).getStaName()); nextLine[j] = nowLine; } else { StringBuffer tmpSbf = new StringBuffer(); for (String str : line_stations.keySet()) { tmpSbf = new StringBuffer(); for (Station s : line_stations.get(str)) { tmpSbf.append(s.getStaName()); } if (tmpSbf.indexOf(list.get(j).getStaName()) != -1 && tmpSbf.indexOf(list.get(k).getStaName()) != -1) { path.put(j, path.get(k) + "\n-->换乘" + str + "\n\t-->" + list.get(j).getStaName()); nextLine[j] = str; } } } } } } } }
个人总结
地铁项目是软件工程课的个人项目,一开始以为可以很容易实现,结果花了不少时间来构思合理的数据结果来存储线路和站点信息,完成所有功能模块后发现其实代码和流程可以更进一步优化,终版代码的复杂度其实是受到了一开始的.txt数据文件的束缚,读取.txt文件需要处理地铁线和站点的之间的站点和所属线路、相邻站点之间的约束关系,代码量和复杂度就相应的增大了不少,通过这次实战,涨了不少经验值,开发初期如果综合考虑.txt数据的存储形式或者数据处理方式,后期可以节省很大的时间精力和开销来编写可读性和可优化性更好的代码。
原文地址:https://www.cnblogs.com/hjw31701010/p/11675158.html
- 以大数据之名,变身!——In big data we trust
- 90%家长都不知道关于少儿编程的这些疑题!
- 常用SQL语句和语法汇总
- Python学习笔记1——斐波那契数列
- 视觉传感器几大技术要点详解!
- Spark之搜狗日志查询实战
- 区块链与数字货币是什么关系呢?
- 保存数据到MySql数据库——我用scrapy写爬虫(二)
- 人工智能将取代人类?危机亦或是新的机遇
- 大数据驱动的未来网络:体系架构与应用场景(下)网络架构与场景详解
- 冷静点,NVIDIA 禁止 Geforce 进数据中心想限制的并不是深度学习
- 智能机器人崛起背后的中国力量
- 企业微服务架构转型-实施步骤
- Andrew Ng机器学习课程笔记--week2(多元线性回归&正规公式)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 带你彻底搞懂-View的工作原理!
- Python 批量下载BiliBili视频 打包成软件
- 必要掌握!Window、WindowManager !
- 面试必备:ThreadLocal+Looper+Handler
- 子线程 真的不能更新UI ?
- Web前端开发 HTML设计 经验与技巧总结
- [OHIF-Viewers]医疗数字阅片-医学影像-辅助工具-Redux DevTools-DevTools for Redux with hot reloading, action replay,
- 全面理解:Android中的线程及线程池
- Ubuntu系统 安装与配置 常见异常与解决办法
- [OHIF-Viewers]医疗数字阅片-医学影像-Module: Panel-自定义面板-中二-Redux&react-redux状态管理详解
- Bitmap的加载和Cache
- Python全栈 Linux基础之2.Linux终端命令简介
- Ubuntu系统 使用与开发 常见异常与解决办法
- 淘宝首页Bug!嵌套滑动及NestedScroll
- 曝光埋点方案:recyclerView中的item曝光逻辑实现