二话不说,先上一张青岛地铁交通图。

我是个在青岛上大学的计算机专业的大二学生,有一次我在烟台的朋友和他的女朋友坐高铁过来找我玩,他在青岛北站下高铁。

我从青岛二中站上车,准备去青岛北站接他,去接他前我已经知道了青岛地铁3号线的一端是青岛站,另一端是青岛北站,于是我选择了相信自己,而不是高德地图。

从上面那个地铁交通图中也能看出来,想要到三号线上去要先换乘到2号线,再换乘到3号线,到了苗岭路站,走到2号线的站台,看着安全门上方的一维交通图,我看到了两个可以换乘到3号线的换乘站,分别是五四广场和李村,并且两个换乘站距离苗岭路差不多,开往五四广场方向的列车先到了,我想都没想就上去了。等真的到了五四广场,哭都来不及呀。五四广场开往青岛北站,也要经过李村!!!并且李村距离青岛北站只隔着3站,而五四广场距离青岛北站整整隔着14站!!!

于是,原本一个小时就能到青岛北站的,却用了两个多小时,白白让朋友和他的女朋友等了我很长一段时间。

我决定,决不能让这种悲剧重演。。。。。。这个学期学了数据结构,就想着用图的知识和C/C++来解决我的问题。

首先,将实际的站点信息抽象成一个结构体数组,将实际站点与数组中的元素一一对接起来。

初始化这个结构体数组:

//站点信息
struct
{int id;int line;int istransfer;char staname[16];
}sta[63]=
{{1,3,0,"青岛北站"},{2,3,0,"永平路"},{3,3,0,"振华路"},{4,3,0,"君峰路"},{5,3,1,"李村"},{6,3,0,"万年泉路"},{7,3,0,"海游路"},{8,3,0,"地铁大厦"},{9,3,0,"长沙路"},{10,3,0,"双山"},{11,3,0,"清江路"},{12,3,0,"错埠岭"},{13,3,0,"敦化路"},{14,3,0,"宁夏路"},{15,3,0,"江西路"},{16,3,1,"五四广场"},{17,3,0,"延安三路"},{18,3,0,"太平角公园"},{19,3,0,"中山公园"},{20,3,0,"汇泉广场"},{21,3,0,"人民会堂"},{22,3,0,"青岛站"},{23,2,0,"泰山路"},{24,2,0,"利津路"},{25,2,0,"台东"},{26,2,0,"海信桥"},{27,2,0,"芝泉路"},{28,2,0,"浮山所"},{29,2,0,"燕儿岛路"},{30,2,0,"高雄路"},{31,2,0,"麦岛"},{32,2,0,"海游路"},{33,2,0,"海川路"},{34,2,0,"海安路"},{35,2,0,"石老人浴场"},{36,2,1,"苗岭路"},{37,2,0,"同安路"},{38,2,0,"辽阳东路"},{39,2,0,"东韩"},{40,2,0,"华楼山路"},{41,2,0,"枣山路"},{42,2,0,"李村公园"},{43,11,0,"会展中心"},{44,11,0,"青岛二中"},{45,11,0,"青岛科大"},{46,11,0,"张村"},{47,11,0,"枯桃"},{48,11,0,"海洋大学"},{49,11,0,"世博园"},{50,11,0,"北宅"},{51,11,0,"北九水"},{52,11,0,"庙石"},{53,11,0,"浦里"},{54,11,0,"鳌山卫"},{55,11,0,"山东大学"},{56,11,0,"蓝色硅谷"},{57,11,0,"水泊"},{58,11,0,"博览中心"},{59,11,0,"温泉东"},{60,11,0,"皋虞"},{61,11,0,"臧村"},{62,11,0,"钱谷山"},{63,11,0,"鳌山湾"}
};

然后选取邻接矩阵作为图的载体,i行j列上的元素为1表示ID为i的站点和ID为j的站点是直接相连的,i行j列上的元素为0表示ID为i的站点和站点为j的站点不是直接相连的。

声明一个表示图的连接关系矩阵的二维数组,并将这个邻接矩阵初始化。

为了让矩阵的行列和站点的ID更好地对应起来,站点ID即为行(或列)的值,第0行和第0列不表示邻接关系。

//表示连接关系的矩阵
int nodelist[65][65];
//将地图初始化
void readgraph()
{//初始化站点总数n=63;//先将矩阵所有元素置零for(i=0;i<65;i++)for(j=0;j<65;j++)nodelist[i][j]=0;//初始化3号线for(i=1;i<22;i++){nodelist[i][i+1]=1;nodelist[i+1][i]=1;}//初始化2号线for(i=23;i<42;i++){nodelist[i][i+1]=1;nodelist[i+1][i]=1;}//初始化11号线for(i=43;i<63;i++){nodelist[i][i+1]=1;nodelist[i+1][i]=1;}//初始化换乘站点的连接信息nodelist[16][27]=1;//连接五四广场和芝泉路nodelist[27][16]=1;//连接芝泉路和五四广场nodelist[16][28]=1;//连接五四广场和浮山所nodelist[28][16]=1;//连接浮山所和五四广场nodelist[5][42]=1;//连接李村和李村公园nodelist[42][5]=1;//连接李村公园和李村nodelist[5][41]=1;//连接李村和枣山路nodelist[41][5]=1;//连接枣山路和李村nodelist[36][43]=1;//连接苗岭路和会展中心nodelist[43][36]=1;//连接会展中心和苗岭路
}

经过初始化后的矩阵图(部分):

解析:整个地铁交通图的站点过于的多,一个一个地初始化代码过于庞杂。某一条地铁线路上的列车就只在一条线路上行使,这给了我启发,可以通过for循环来批量连接各个站点,就像列车沿着某一条线路行驶将该线路串起来一样,从3号线开始,先将3号线串起来,再将2号线串起来,再将1号线串起来,依次将nodelist[i][i+1]置为1,最后统一处理换乘站点的连接信息。

再就是最为关键的环节——求解最短路径。

求解最短路径的算法用到了图的广度优先搜索,学过数据结构的人都知道,广度优先搜索算法依托的数据结构是队列,因此我们先要解决好队列的问题。如果使用的是C++的编译环境,可以选择#include<queue>;如果使用的是纯C语言的编译环境,队列就需要建一个<Queue.h>头文件自己去实现,下面是纯C语言实现<Queue.h>的代码:

#ifndef QUEUE_H_INCLUDED
#define QUEUE_H_INCLUDED
//队列结构体
typedef struct
{int q[10000];//队头、队尾int f,r;
}queue;
//入队操作
void enq(queue *Q,int x)
{Q->q[Q->r]=x;if(Q->r==9999)Q->r=0;elseQ->r++;if(Q->r==Q->f)printf("队溢出!\n");
}
//取队头元素
int front(queue *Q)
{if(Q->r==Q->f){printf("front函数:队空!\n");return 0;}elsereturn Q->q[Q->f];
}
//出队操作
void dep(queue *Q)
{if(Q->r==Q->f)printf("dep函数:队空!\n");else{if(Q->f==9999)Q->f=0;elseQ->f++;}
}
//判断队列是否为空队列
int qempty(queue Q)
{if(Q.f==Q.r)return 1;elsereturn 0;
}
#endif // QUEUE_H_INCLUDED

队列的一系列操作被实现后,就可以通过图的广度优先遍历求解最短路径了,最短路径将被保存在整型数组z[65]中,观察寻找最短路径函数中的while循环,每找到一个可访问的结点,就将该结点上一个结点的id存放在该可访问结点对应的z数组元素中。例如,结点j可访问,结点j是通过结点i访问到的,那么就让z[j]=i。

另外还有一些其他的全局变量:

//队列声明
queue Q;
//队列声明
queue Q;
//起点和终点
int a,b;
//站点总数
int n;
int i,j,x,y;
//判断是否结束的标志
int finished;

求解最短路径的函数:

//寻找最短路径
void shortest(int a,int b)
{if(a==b)nodelist[a][a]=2;else{enq(&Q,a);nodelist[a][a]=2;finished=0;while(!qempty(Q)&&!finished){//取队头结点a=front(&Q);//删除一个队头结点dep(&Q);//从ID为1的结点开始checkj=1;while(j<=n&&!finished){//必须保证结点j和刚出队的结点a直接相连//且结点j没有被访问过if(nodelist[a][j]==1&&nodelist[j][j]!=2){enq(&Q,j);//标志结点j已经被访问过nodelist[j][j]=2;//保证能够通过z[j]索引到结点az[j]=a;//广度优先遍历到达终点if(j==b){finished=1;}}if(!finished)j++;}}if(!finished)printf("没有路径!");}
}

解析:从顶点A开始,依次访问与A邻接的顶点VA1,VA2,,...,VAK,将上述顶点访问一遍后,若没有访问B,则继续访问与VA1邻接的顶点VA11,VA12,...,VA1M,再访问与VA2邻接的顶点......如此下去,直到找到B。最先到达B的路径,一定是边数最少的路径。采用队列记录被访问过的顶点,每次访问与队头相邻接的顶点,然后将队头顶点出队。若队空,则说明A到B不存在通路。其中,nodelist[i][i]=1表示站点id为i的顶点在寻找最短路径的过程中已经被访问过。

最后将最短路径显示到屏幕上,这一部分不同的界面有不同的显示方法,下面是DOS界面显示最短路径的函数:

void writepath(int a,int b)
{i=b;while(i!=a){if(sta[i-1].istransfer){printf("|换乘|");}else{printf("|%d号线|",sta[i-1].line);}printf("%s <- ",sta[i-1].staname);i=z[i];}if(!sta[a-1].istransfer){printf("|%d号线|",sta[a-1].line);}printf("%s",sta[a-1].staname);printf("\n");
}

下面是DOS界面下的运行结果:

下面是将算法搬运到QT中,用QT将数据可视化后的运行结果:

欢迎大家关注/订阅我的微信公众号Code Art Online,我会在我的公众号分享个人见闻,发现生活趣味;这里不仅有0和1,还有是诗和远方↓↓↓

地铁交通咨询系统的设计与实现相关推荐

  1. 交通咨询系统的设计(数据结构 C语言)

    一.实验目的 1)熟悉并掌握图的存储结构: 2)熟悉并掌握单个最短路径算法: 3)熟悉并掌握任意两个顶点之间的最短路径算法. 二.实验内容 设计一个交通咨询系统,能让乘客咨询从一个城市顶点到另一个城市 ...

  2. 青岛地铁交通咨询系统

    大二课程<数据结构>课程设计项目,仅供参考 C++&QT 项目地址 1.(重要)后台数据处理:使用图结构存储数据,利用最短路径选择算法进行路径选择: 2.检测输入框是否为空及输入合 ...

  3. 用c语言设计交通咨询系统,交通咨询系统设计课程设计.doc

    交通咨询系统设计课程设计 课 程 设 计 报 告 课程名称 数据结构 课题名称 交通咨询系统 专 业 班 级 学 号 姓 名 指导教师 2013 年 月 日 设计内容与设计要求 1设计内容 [问题描述 ...

  4. 我的第一篇课程设计(交通咨询系统)

    我因为当时课设选题的时候,不想随随便便,又我看了下那些题目,也就这个最难,而且我又注意到文档的修改日期,是2017年,所以就认为老师给老课题给我们做,是怕我们交不起作业,也由于老师自己长年教这课设,代 ...

  5. 太原理工大学2021数据结构课程设计(交通咨询系统(最短路径问题))

    太原理工大学数据结构课程设计(交通咨询系统(最短路径问题)) 声明:这里只是给出核心代码 核心代码指程序的计算部分,不是完整程序 背景题目 给定一个 n 个点 m 条边的无向图,图中可能存在重边和自环 ...

  6. 地铁收费系统课程设计总结

    文章目录 前言 一.总体说明 1.1 算法设计规则 1.2 约束 二.操作说明 2.1初始化 2.2 请求扣费 2.3 查询扣费日志 2.4 查询扣费历史记录 2.5 注销票卡 三.附录 3.1 命令 ...

  7. 消防应急照明和疏散指示系统在轨道交通中的设计应用

    摘要:本文分析了消防应急照明和疏散指示系统的特点与设计要点,介绍了系统在城市轨道交通中的设计应用,轨道交通设计中新的消防应急照明和疏散指示系统的备用照明仍由EPS供电,新增一套疏散指示照明系统,增加疏 ...

  8. 交通咨询系统(最短路径问题)

    [问题描述] 在交通网络非常发达.交通工具和交通方式不断更新的今天,人们在出差.旅游或做其他出行时,不仅关心节省交通费用,而且对里程和所需要的时间等问题也感兴趣.对于这样一个人们关心的问题,可用 一个 ...

  9. 店铺咨询系统c语言,交通咨询系统数据结构c语言word文档良心出品

    <交通咨询系统数据结构c语言word文档良心出品>由会员分享,可在线阅读,更多相关<交通咨询系统数据结构c语言word文档良心出品(22页珍藏版)>请在人人文库网上搜索. 1. ...

最新文章

  1. 一个用微软官方的OpenXml读写Excel 目前网上不太普及的方法。
  2. SharePoint Server 2007 Web内容管理中的几个关键概念
  3. 基础 - #pragma pack (n) 设置对齐方式
  4. 【渝粤教育】国家开放大学2019年春季 1398分析化学(本) 参考试题
  5. 创建预编译头 Debug 正常 Release Link Error:预编译头已存在,使用第一个 PCH
  6. datetime默认当前时间_简述Python培训之time和datetime的区别
  7. mysql数据库登录历史_mysql数据库查看历史记录
  8. Kaggle信用卡欺诈数据
  9. 思博伦仪表SRV4(ISIS)测试指南
  10. matlab小波分析工具箱,matlab小波分析工具箱
  11. c语言补码取反后什么意思,补码为什么取反加一
  12. “一键淘宝”将淘宝网店免费转移到手机客户端android教程
  13. scapy(二):基于流量分析的SQL注入检测
  14. css 魔方,css 3d旋转魔方
  15. XSS盗取用户信息实验(详细)及xss之旅闯关
  16. python小游戏贪吃蛇下载_python实现贪吃蛇小游戏
  17. 转---电脑的MAC实际地址可以修改吗?
  18. 解决公众号网页 微信免登录 重定向 地址 只能带一个参数问题
  19. 电商网络支付结算风险与防范
  20. vuejselectron-vue----朝花夕拾.

热门文章

  1. Zabix,web访问提示Database error No route to host
  2. Angular5 避免重复请求
  3. 【MongoDB】什么是MongoDB?MongoDB有什么特点?MongoDB的适用场景?
  4. httpd: Could not reliably determine the server‘s fully qualified domain name
  5. 怎样用matlab打开csv文件
  6. 矩阵sp.coo_matrix()
  7. 在 Flutter 应用程序中通过定制服务进行本地化
  8. grafana 画拓扑图 能不能_干货|告诉你标准漂亮的网络拓扑图是怎么画出来的?...
  9. LoRa开发|LoRa(SX1276/8)串口透传代码-将LoRa封装成单独的驱动(STM32)
  10. 蓝桥杯嵌入式第十三届第一场省赛真题