地铁线路最短路径
计算地铁线路两站间最短路径方案
主要功能
以北京地铁线路图为样例,包含交叉线路以及环线。要求指定两站之间最短(最少经过站数)乘车路线;输出指定地铁线路的所有站点,通过最短路径算法计算地铁线路两站间最短距离,获取最佳线路方案。
北京地铁线路
功能需求
提供一副地铁线路图,计算指定两站之间最短(最少经过站数)乘车路线;输出指定地铁线路的所有站点。
性能需求
任意两站最短路线,支持环线的查询。可以加载不同城市的地铁线路。考虑存在两个无法连通的情况,输出无方案。
可靠性和可用性需求
时间复杂度小于O(n^3)。
实现语言
python
实现算法
BFS算法:
- 把初始节点作为路径放入队列
- 每次从每次从队首取出一条路径,遍历这条路径末尾节点的所有相邻节点,把它们构成新的路径放入队尾。
- 如果当前路径末尾节点是目标节点,结束程序
- 如果遍历所有路径都没找到目标节点,结束程序
核心代码
读取地图
地图文件名 subway.txt
# 读取文件 def FileRead(): # lines_dict字典,键:线路 值:拥有站点 lines_dict = dict() FILE_STORAGE_WAY = 'subway.txt' ifile = open(FILE_STORAGE_WAY, 'r',encoding='utf-8') # 按行读取 fileLine = ifile.readline() while len(fileLine) > 0: # 去除末尾换行、前后空格(不包括字符串中间的空格) fileLine = fileLine.split("\n")[0].strip() # 以线路为键、站点字符串组为值,存入lines_dict字典中 lines_dict[fileLine.split(" ")[0]] = fileLine[fileLine.find(" ")+1:].split() fileLine = ifile.readline() # print(lines_dict) return lines_dict
BFS搜索
# 广度优先遍历 def BFS(start, goal): # 起点和终点相同直接输出 if start == goal: return [start] # 存放已经过站点集合 explored = set() # queue队列存放遍历过程中生成的不同路径 # 先存入开始站点 station_queue = [ [start] ] # 遍历队列 while station_queue: # 将队列中的第一条路径取出 path = station_queue.pop(0) # 获取该路径最后一个站点,即该路径已抵达站点 station = path[-1] # 遍历该站点的领接站点 for state, line in stations_dict[station].items(): # 如果该领接站点未遍历过 if state not in explored: # 添加到已经过线路 explored.add(state) # 将该路径延长至该领接站点 path2 = path + [line, state] # 如果到达终点则退出,返回当前路径 if state == goal: return path2 # 没到终点,则加入存放遍历过程中不同路径队列的队尾 else: station_queue.append(path2) # 遍历完为空返回空 return []
构建站点信息
# 为每个站台构建字典 def build_subway(lines_dict): stations_set = set() # 遍历各条线路,站点名称存入stationsSet,名称不重复 for line in lines_dict.keys(): # print(stations[line]) stations_set.update(set(lines_dict[line])) # 站点组 stations_dict = {} for station in stations_set: # 领接站点组 next_station_dict = {} for line in lines_dict: if station in lines_dict[line]: # 获取该线路所有站点 stations = lines_dict[line] # 获取当前站点在线路中的下标 index = stations.index(station) # 将领接站点为键,线路为值,构建字典 # 站点在首位 if index == 0: next_station_dict[stations[1]] = line # 环路条件:首站和尾站相同 # 是环路,添加倒数第二站为相邻站点 if stations[0] == station and stations[-1] == station: next_station_dict[stations[-2]] = line # 站点在末位 elif index == len(stations)-1: next_station_dict[stations[index-1]] = line # 站点在中间位置 else: next_station_dict[stations[index-1]] = line next_station_dict[stations[index+1]] = line # 将该站点作为键,领接站点字典为值,构建字典 stations_dict[station] = next_station_dict return stations_dict
输出方案
将BFS搜索的结果按格式输出
def findway(start,goal): # 查询方案输出路径 str = BFS(start,goal) print(start,'->',goal) count = 0 for value in str: print(value, end=' ') count+=1 if((count) % 10 == 0): print() print()
main函数
读取地图、调用输出方案
if __name__ == '__main__': stations_dict = build_subway(FileRead()) # 读取地图 start = input('请输入起点站:').strip() # 去除字符前后空格 goal = input('请输入终点站:').strip() try: findway(start,goal) except: print("站台可能不存在") # print('\n2号环线端点测试:') # findway("西直门","积水潭") # findway("积水潭","西直门") # # print('\n10号环线端点测试:') # findway("火器营","巴沟") # findway("巴沟","火器营") # # print('\n站点自身测试:') # findway("巴沟", "巴沟") # findway("花园桥", "花园桥") # # print('\n中线路测试:') # findway('万安','三元桥') # findway("金安桥", "西局") # findway('中关村','北京站') # # print('\n长线路测试:') # findway('巩华城','肖村') # findway('万寿路','望京东') # findway('金安桥','大郊亭')
subway.txt
格式如下
单向线: 线路名 站台1 站台2 …… 站台n
环线: 线路名 站台1 站台2 …… 站台n 站台1
1号线 苹果园 古城 八角游乐园 八宝山 玉泉路 五棵松 万寿路 公主坟 军事博物馆 木樨路 南礼士路 复兴门 西单 天安门西 天安门东 王府井 东单 建国门 永安里 国贸 大望路 四惠 四惠东 2号线 西直门 积水潭 鼓楼大街 安定门 雍和宫 东直门 东四十条 朝阳门 建国门 北京站 崇文门 前门 和平门 宣武门 长椿街 复兴门 阜成门 车公庄 西直门 4号线大兴线 安河桥北 北宫门 西苑 圆明园 北京大学东门 中关村 海淀黄庄 人民大学 魏公村 国家图书馆 动物园 西直门 新街口 平安里 西四 灵境胡同 西单 宣武门 菜市口 陶然亭 北京南站 马家堡 角门西 公益西桥 新宫 西红门 高米店北 高米店南 枣园 清源路 黄村西大街 黄村火车站 义和庄 生物医药基地 天宫院 5号线 天通苑北 天通苑 天通苑南 立水桥 立水桥南 北苑路北 大屯东路 惠新四街北口 惠新四街南口 和平西桥 和平里北街 雍和宫 北新桥 张自忠路 东四 灯市口 东单 崇文门 磁器口 天坛东门 蒲黄榆 刘家窑 宋家庄 6号线 海淀五路居 慈寿寺 花园桥 白石桥南 车公庄西 车公庄 平安里 北海北 南锣鼓巷 东四 朝阳门 东大桥 呼家楼 金台路 十里堡 青年路 褡裢坡 黄渠 常营 草房 物资学院路 通州北关 北运河西 郝家府 东夏园 潞城 7号线 北京西站 湾子 达官营 广安门内 菜市口 虎坊桥 珠市口 桥湾 磁器口 广渠门内 广渠门外 九龙山 大郊亭 百子湾 化工 南楼梓庄 欢乐谷景区 双合 焦化厂 8号线 朱辛庄 育知路 平西府 回龙观东大街 霍营 育新 西小口 永泰庄 林萃桥 森林公园南门 奥林匹克公园 奥林中心 北土城 安华桥 安德里北街 鼓楼大街 什刹海 南锣鼓巷 中国美术馆 8号线南段 珠市口 天桥 永定门外 木樨园 海户屯 大红门南 和义 东高地 火箭万源 五福堂 德茂 瀛海 9号线 郭公庄 丰台科技园 科怡路 丰台南路 丰台东大街 七里庄 六里桥 六里桥东 北京西站 军事博物馆 白堆子 白石桥南 国家图书馆 10号线 巴沟 苏州街 海淀黄庄 知春里 知春路 西土城 牡丹园 健德门 北土城 安贞门 惠新西街南口 芍药居 太阳宫 三元桥 亮马桥 农业展览馆 团结湖 呼家楼 金台夕照 国贸 双井 劲松 潘家园 十里河 分钟寺 成寿寺 宋家庄 石榴庄 大红门 角门东 角门西 草桥 纪家庙 首经贸 丰台站 泥洼 西局 六里桥 莲花桥 公主坟 西钓鱼台 慈寿寺 车道沟 长春桥 火器营 巴沟 13号线 西直门 大钟寺 知春路 五道口 上地 西二旗 龙泽 回龙观 霍营 立水桥 北苑 望京西 芍药居 光熙门 柳芳 东直门 14号线东段 善各庄 来广营 东湖渠 望京 阜通 望京南 将台 东风北桥 枣营 朝阳公园 金台路 大望路 九龙山 平乐园 北工大西门 十里河 方庄 蒲黄榆 景泰 永定门外 北京南站 14号线西段 西局 七里庄 大井 郭庄子 大瓦窑 园博园 张郭庄 15号线 俸伯 顺义 石门 南法信 后沙峪 花梨坎 国展 孙河 马泉营 崔各庄 望京东 望京 望京西 关庄 大屯路东 安立路 奥林匹克公园 北沙滩 六道口 清华东路西口 16号线 北安河 温阳路 稻香湖路 屯佃 永丰 永丰南 西北旺 马连洼 农大南路 西苑 八通线 四惠 四惠东 高碑店 传媒大学 双桥 管庄 八里桥 通州北苑 果园 九棵树 梨园 临河里 土桥 昌平线 昌平西山口 十三陵景区 昌平 昌平东关 北邵洼 南邵 沙河高教园 沙河 巩华城 朱辛庄 生命科学园 西二旗 房山线 阎村东 苏庄 良乡南关 良乡大学城西 良乡大学城 良乡大学城北 广阳城 篱笆房 长阳 稻田 大葆台 郭公庄 首都机场线 T3航站楼 T2航站楼 三元桥 东直门 西郊线 巴沟 颐和园西门 茶棚 万安 植物园 香山 燕房线 阎村东 紫草坞 阎村 星城 大石河东 马各庄 饶乐府 房山城关 燕山 亦庄线 宋家庄 肖村 小红门 旧宫 亦庄桥 亦庄文化园 万源街 荣京东街 荣昌东街 同济南路 经海路 次渠南 次渠 亦庄火车站
测试结果
出错处理需求
遇到不存在的地铁站抛出异常。
接口需求
字符串输入
约束逆向需求
如果两个城市间地铁无连通,只支持同一城市市内查询,不可跨市。
将来可能提出的要求
支持加权地铁线路最短路径查询。支持线路时间估计。排除不在运营范围内的线路。