基于图结构实现地铁乘坐线路查询

github-python算法和flaskapp部分:repo

github-android部分:repo

flaskapp接口文档:传送门

深度了解Dijkstra优化算法:传送门

问题描述

编写一个程序实现地铁最短乘坐(站)线路查询,输入为起始站名和目的站名,输出为从起始站到目的站的最短乘坐站换乘线路。

1.采用Dijkstra算法实现,使用优先队列对性能进行了优化;

2.如果两站间存在多条最短路径,则输出其中的一条即可;

本次项目实现采用了flask作为后端提供接口服务,使用androidApp进行get请求获得数据,显示在Textview中

设计需求

确定储存地铁站文件的格式文件 (已确认使用json格式和文本格式)

确定读取地铁站数据的方式 (使用python的file打开命令)

确定获取两站点最小站点数的算法方式

进行外表封装

进行输出格式的确定

性能测试

最后结果检查

数据存储格式

stationline.txt文本为存储的地图数据文本,格式如下图所示:

使用0与1来分别表示是否需要换乘

地铁线路条数

线路x 线路x站数

站名1 是否需要换乘

站名2 是否需要换乘

...

数据示例

2 20

曹庄 0

卞兴 0

芥园西道 0

咸阳路 0

长虹公园 1

广开四马路 0

西南角 1

鼓楼 0

东南角 0

建国道 0

天津站 1

远洋国际中心 0

顺驰桥 0

靖江路 1

翠阜新村 0

屿东城 0

登州路 0

国山路 0

数据文本读取代码

with open(os.path.join(os.path.abspath('..'), "station/stationLine.txt"), "r") as f:

TOTAL = f.readline()

for line in f.readlines():

if line != '\n':

line = line.rstrip('\n')

line = line.split(' ')

if line[0] in LINEDATA:

linei = line[0]

continue

line[1] = linei

line0 = line[0]

intline = int(line[1])

if intline not in data.keys():

data[intline] = []

data[intline].append(line0)

else:

data[intline].append(line0)

if line0 not in datanum.keys():

datanum[line0] = [intline]

else:

datanum[line0].append(intline)

打印结果

stationline {"1": ["刘园", "西横堤", "果酒厂", "本溪路", "勤俭道", "洪湖里", "西站", "西北角", ..]}

linesdata {"刘园": [1], "西横堤": [1], "果酒厂": [1], "本溪路": [1], "勤俭道": [1], "洪湖里": [1], "西站": [1, 6], "西北角": [1], "西南角": [1, 2], "二纬路": [1], "海光寺": [1], "鞍山道": [1], "营口道": [1, 3], "小白楼": [1], "下瓦房": [1, 5],....}

station_num {"刘园": 0, "西横堤": 1, "果酒厂": 2, "本溪路": 3, "勤俭道": 4, "洪湖里": 5, "西站": 6, "西北角": 7, "西南角": 8, "二纬路": 9, "海光寺": 10, "鞍山道": 11, "营口道": 12, "小白楼": 13, "下瓦房": 14,.....}

获得点与点之间的最短路径:

def find_shortest_path(graph, start, end, path=[]):

# 查找最短路径

path = path + [start]

if start == end:

return path

if not start in graph.keys():

return None

shortest = None

for node in graph[start]:

if node not in path:

newpath = find_shortest_path(graph, node, end, path)

if newpath:

if not shortest or len(newpath) < len(shortest):

shortest = newpath

return shortest

def find_all_paths(graph, start, end, path):

# 查找所有的路径

path = path + [start]

if start == end:

return [path]

if not start in graph.keys():

return []

paths = []

for node in graph[start]:

if node not in path:

newpaths = find_all_paths(graph, node, end, path)

for newpath in newpaths:

paths.append(newpath)

return paths

pathss = {}

for i in range(I):

for j in range(I):

if RouteGraph.get_edge(i, j) == 1:

start = STATIO[i]

end = STATIO[j]

if i not in pathss.keys():

pathss[i] = [j]

else:

pathss[i].append(j)

# pathss是记录每个站点接触的站点list

# print(pathss)

dijkstra算法具体分析

def dijkstra_shortest_pathS(graph, v0, endpos):

vnum = 0

for i in pathss.keys():

vnum += 1

assert 0 <= v0 < vnum

# 长为vnum的表记录路径

paths = [None] * vnum

count = 0

cands = PrioQueue([(0, v0, v0)])

while count < vnum and not cands.is_empty():

plen, u, vmin = cands.dequeue()

if paths[vmin]:

continue

paths[vmin] = (u, plen)

# print(u, plen)

for v in graph[vmin]:

if not paths[v]:

cands.enqueue((plen + 1, vmin, v))

count += 1

return paths

stationController 部分

# encoding=utf-8

import os

import json

from stationplan import computefshortestpath

from stationplan import getInfo

def getShort(start, end):

stationnum, s = computefshortestpath(start, end)

return stationnum, s

def getInfoStation():

stationnumlist, stationlist = getInfo()

return stationnumlist, stationlist

if __name__ == "__main__":

a, b = getInfoStation()

print(type(a))

print(type(b))

stationController中具体使用的函数分析

# 确定出发点和最后的站点

def computefshortestpath(startpos, endpos):

s1 = STATION_NUM[startpos]

e1 = STATION_NUM[endpos]

# print(s1,e1)

paths = dijkstra_shortest_pathS(pathss, s1, e1)

# print(paths)

b = []

p = paths[e1][0]

# print(paths[e1])

b.append(STATIO[p])

while True:

p1 = paths[p][0]

p = p1

b.append(STATIO[p])

if p == s1:

break

b.reverse()

if s1 != e1:

b.append(STATIO[e1])

stationnumo = len(b)

s = ""

s += b[0]

for i in range(1, len(b) - 1):

a1 = set(datanum[b[i - 1]])

b1 = set(datanum[b[i + 1]])

c1 = set(datanum[b[i]])

# 如果没有交集,说明不是同一条路,对当前站点前后站点进行分析,如果两个站点属于

# 的站点线号没有发生重叠,说明当前线路在该站点没有进行换乘

if not len(a1 & b1):

if len(datanum[b[i + 1]]) != 0:

s += "-" + str((list(set(datanum[b[i]]) & b1)[0])) + "号线"

s += "-" + b[i]

else:

s += "-" + b[i]

s += "-" + b[len(b) - 1]

return stationnumo, s

def getInfo():

return data, STATION_NUM

flask app的分析:

flask具体作用类似与springboot,是python后端的一个框架,对新手及其友好,而json包则是用来处理json输出格式的一个工具

# encoding=utf-8

from flask import Flask, request

from stationController import getShort

from stationController import getInfoStation

import json

app = Flask(__name__)

@app.route('/getStationInfo', methods=['GET'])

def getStationInfo():

num = request.args["num"]

num = int(num)

data, stationlist = getInfoStation()

if not num:

result = {

"code": 500,

"msg": "the service make a mistake -.-"

}

else:

strmsg = data[num]

print(strmsg)

result = {

"code": 0,

"msg": strmsg

}

return json.dumps(result)

@app.route('/getShortestPath', methods=['GET'])

def getShortestPath():

start = request.args['start']

end = request.args['end']

data, stationlist = getInfoStation()

print(start not in stationlist.keys() and end not in stationlist.keys)

if (not start or not end) or (start not in stationlist.keys() or end not in stationlist.keys()):

result = {

"code": 501,

"msg": "please input the correct start and end station -.-"

}

else:

stationnum, strmsg = getShort(start, end)

result = {

"code": 0,

"msg": strmsg,

"stationnum": stationnum

}

return json.dumps(result)

if __name__ == '__main__':

app.run(host="0.0.0.0", port=80)

flask具体demo已经部署在服务器上,返回信息,请求方式等具体请查看接口文档:传送门

安卓部分

编译器使用AS进行开发

使用友好的流线式布局进行开发

布局代码如下:

<?xml version="1.0" encoding="utf-8"?>

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:paddingBottom="10dp"

android:paddingLeft="10dp"

android:paddingRight="10dp"

android:paddingTop="30dp"

android:orientation="vertical"

tools:context=".MainActivity" >

android:id="@+id/textView1"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="请选择站点线路起点线" />

android:layout_width="match_parent"

android:layout_height="141dp"

android:layout_gravity="center"

android:orientation="vertical">

android:id="@+id/spinner1"

android:layout_width="match_parent"

android:layout_height="50dp" />

android:id="@+id/spinner2"

android:layout_width="match_parent"

android:layout_height="50dp"

android:layout_marginTop="20dp" />

android:id="@+id/textView2"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="请选择站点线路终点线" />

android:layout_width="match_parent"

android:layout_height="141dp"

android:layout_gravity="center"

android:orientation="vertical">

android:id="@+id/spinner3"

android:layout_width="match_parent"

android:layout_height="50dp" />

android:id="@+id/spinner4"

android:layout_width="match_parent"

android:layout_height="50dp"

android:layout_marginTop="20dp"

/>

android:id="@+id/searchButton"

android:layout_width="match_parent"

android:layout_height="40dp"

android:text="搜索最短路线">

android:id="@+id/showShortestPath"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:text="">

对与spinner(下拉框的集联操作使用xml进行了储存)

当选中相应的station值时进行选择第二个spinner中的应该显示的值

格式如下

<?xml version="1.0" encoding="utf-8"?>

-站点线路-

1

2

3

5

6

9

-站点-

刘园

西横堤

果酒厂

本溪路

勤俭道

洪湖里

西站

西北角

西南角

二纬路

海光寺

鞍山道

营口道

小白楼

下瓦房

南楼

土城

陈塘庄

复兴门

华山里

财经大学

双林

李楼

......

代码控制:

....

if (pro.equals("1")) {

cityAdapter = ArrayAdapter.createFromResource(

MainActivity.this, R.array.station1,

android.R.layout.simple_spinner_dropdown_item);

sr4.setAdapter(cityAdapter);

sr4.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

@Override

public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

String strstation = MainActivity.this.getResources().getStringArray(R.array.station1)[position];

sr4Val = strstation;

}

@Override

public void onNothingSelected(AdapterView<?> parent) {

}

});

}

.....

demo图

使用okhttps获得json数据,get方式

相应的as添加jar包方式:

打开路径:file->project Structure->Depndences->app->+号 搜索相应的包即可

博主用的是 okhttp:2.7.5的包

public void SendGetRequest(final String url,final String startpos,final String endpos){

new Thread(new Runnable() {

@Override

public void run() {

try {

OkHttpClient client = new OkHttpClient();//创建OkHttpClient对象

Request request = new Request.Builder()

.url("http://139.9.90.185/getShortestPath?start="+startpos+"&end="+endpos)//请求接口。如果需要传参拼接到接口后面。

.build();//创建Request 对象

Response response = null;

response = client.newCall(request).execute();//得到Response 对象

if (response.isSuccessful()) {

Log.d("kwwl","response.code()=="+response.code());

Log.d("kwwl","response.message()=="+response.message());

// Log.d("kwwl","res=="+response.body().string());

String resdata = response.body().string();

System.out.println(resdata);

//此时的代码执行在子线程,修改UI的操作请使用handler跳转到UI线程。

JSONObject jsonObject = new JSONObject(resdata);

String code = (jsonObject.getString("code"));

if(Integer.parseInt(code)==0) {

String resultpath = (jsonObject.getString("msg"));

String resultnum = (jsonObject.getString("stationnum"));

show("站点数:" + resultnum + "\n" + "站点最短路径:" + resultpath);

Toast.makeText(MainActivity.this,"正在搜索中,请稍后",Toast.LENGTH_SHORT).show();

}else{

String msg = (jsonObject.getString("msg"));

show("提示信息:"+msg);

Toast.makeText(MainActivity.this,"提示信息:"+msg,Toast.LENGTH_SHORT).show();

}

// System.out.println(result);

}else{

show("请求出错,请选择正确的站点请求");

Toast.makeText(MainActivity.this,"请求出错,请选择正确的站点请求",Toast.LENGTH_SHORT).show();

}

} catch (Exception e) {

e.printStackTrace();

}

}

}).start();

}

//显示在下方的TextView中

private void show(final String result) {

runOnUiThread(new Runnable() {

@Override

public void run() {

textShowPaths.setText(result);

}

});

}

python地铁查询系统_基于图结构实现地铁乘坐线路查询相关推荐

  1. 基于图结构实现地铁乘坐线路查询

    基于图结构实现地铁乘坐线路查询 github-python算法和flaskapp部分:repo github-android部分:repo flaskapp接口文档:传送门 深度了解Dijkstra优 ...

  2. JAVA实现查询系统_基于jsp的车辆查询系统-JavaEE实现车辆查询系统 - java项目源码...

    基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的车辆查询系统, 该项目可用各类java课程设计大作业中, 车辆查询系统的系统架构分为前后台两部分, 最终实现在线上 ...

  3. python地铁查询系统_基于Python的苏州实时公交/地铁接口调用代码实例

    1.[代码][Python]代码 #!/usr/bin/python # -*- coding: utf-8 -*- import json, urllib from urllib import ur ...

  4. 城市公交线路查询系统mysql_基于Java环境下的城市公交查询系统设计与实现毕业论文+开题报告+答辩PPT+演示视频+设计源码+Mysql文件...

    摘  要 随着城市现代化和智能化程度的不断提高,城市交通的通畅受到了极大的挑战,便利的出行成为越来越多人的追求,但目前的公交查询系统平台质量普遍不高,路线选择单一,信息更新不及时,查询效率不高等问题存 ...

  5. java农产品查询系统_基于java的农产品销售系统的设计与实现论文.docx

    基于java的农产品销售系统的设计与实现论文.docx 分类号_______________ 密级________________ UDC _______________ 学号_毕业设计(论文)论文题 ...

  6. java农产品查询系统_基于jsp的农产品溯源管理系统-JavaEE实现农产品溯源管理系统 - java项目源码...

    基于jsp+servlet+pojo+mysql实现一个javaee/javaweb的农产品溯源管理系统, 该项目可用各类java课程设计大作业中, 农产品溯源管理系统的系统架构分为前后台两部分, 最 ...

  7. python开发bs系统_基于BS架构的招聘管理系统的开发

    基于 B/S 架构的招聘管理系统的开发 近年来 , 伴随着中国在全球经济的地位日益强大 , 中国国内企业处于迅速发 展阶段.企业的发展离不开人才的引进和更新 , 而这也相继带来了人力资源管理 的巨大发 ...

  8. python条形码识别系统_基于Python与Zbar的无人机盘点条形码识别研究

    2018 年 第 6 期 第 4 0 卷 总 第 2 8 8 期 物流工程与管理 LOGISTICS ENGINEERING AND MANAGEMENT 物流技术 doi :10.3969/ j . ...

  9. 基于python的旅游系统_基于python的去哪儿网旅游数据分析

    20011 基于python的去哪儿网旅游数据分析 运行视频.代码等: 链接:https://pan.baidu.com/s/1tw4Qvtcuwt7ys36M7HvLSg 提取码:1589 复制这段 ...

最新文章

  1. 贺州学院计算机协会,2019年广西高等教育学会数学教学专业委员会年会暨学术交流会在贺州学院召开...
  2. CMS发生FullGc分析
  3. Android内存分析和调优
  4. 在Matlab符号计算中灵活运用assume
  5. leetcode 111 --- 二叉树最小深度
  6. 前端笔记-webpack加载前端资源(图片,css等)
  7. java接口_Java接口
  8. Python(五):list、tuple
  9. 基于BOLT的仿迅雷加速器界面开发(一)
  10. vc模拟 tabletpc_KB895953-TCServer.exe TabletPC崩溃/内存泄漏HotFix
  11. lenovo服务器换系统重装系统_电脑怎么重装系统lenovo
  12. 只用一个div制作太极图
  13. flashfxp 命令行
  14. 全连接网络实现Fashion数据集学习/预测
  15. CSS基础-09-布局(定位 position、浮动float,元素对其、图像对其、文本对齐、元素内内容对齐,元素堆叠)
  16. 12306之梆梆加固libsecexe.so的脱壳及修复
  17. Nginx反向代理+PHP服务器搭建
  18. java如何在控制台重定向_R - 控制台输出重定向不能(可靠地)从函数调用中工作...
  19. Python模拟post提交表单数据 ——某二手车网站回拨电话的分析与利用
  20. 实验六201771010101 白玛次仁

热门文章

  1. 华工《计算机应用基础 简答题》,华工《计算机应用基础》随堂练习
  2. drat中const和final
  3. 西北乱跑娃 --- python爬虫
  4. 脚本木马的制作与原理
  5. 运维管理系统,效果稳定、可靠运行
  6. PageUtils后端常用分页工具类
  7. C++ STL之set详解
  8. [转载] 全本张广泰——第十二回 广泰退贼寇 技惊哈大人
  9. 医院wifi覆盖解决方案
  10. OpenGL显示窗口重定形函数