Qt地铁智慧换乘系统浅学( 三 )最少路径和最少换乘实现

本算法全都基于广度优先

  • 概念
  • 最短路径实现
    • 所用容器
    • 算法思路
  • 最少换乘实现
    • 所需容器
    • 算法思路
  • 成果展示
  • 代码实现
    • 判断是最短路径还是最少换乘
    • 最短路径代码实现
    • 最少换乘代码实现
    • 根据所得List画出线路
  • ui界面的维护(前提条件)
    • 界面
    • 初始化combox控件
    • 建立槽函数

概念

概念这里不过多介绍,很多文章介绍
大体意思是队列思想,每次入队相邻的节点,按照队列以此调用
这里如果想要实现最短路,最少换乘的话,需要用到优先队列
在以上的基础上,对队列进行dist距离的排序,或者trans换乘次数的排序
每次去除最少的,也类似于贪心

最短路径实现

所用容器

typedef std::pair<int,int> PII;  //dist trans
typedef std::pair<QString,QString> nodea; //stationname linename
typedef std::pair<PII,nodea> PLL;  //dist trans ..... ....
QMap<QString,int> dist; //距离表
QMap<QString,int> trans; //换乘
QMap<nodea,bool> final; //是否遍历过
QMap<QString,nodea>pre;  //父节点维护
std::priority_queue<PLL,std::vector<PLL >, std::greater<PLL > > q;  ///优先队列 每次取dist最少的节点

算法思路

这里我们实现了最短路径下最少换乘


1 将换乘表 和 距离表全部设置为INTMAX2 将起点的 换成表 和 距离表 设置为 0
3 将出发站信息存储到优先队列q中 { {00}{startstr , linename} } 注意(出发点可能有多个,出发点有可能属于多个线路)
4 将pre[startstr]赋值为{ "00","00"} 方便还原路径时截止
5 进入while循环 每次取top值 ,为换乘最少的站 ,判断final[top.second]是否为true,如果已经遍历过 那么continue ,否则 final[top.second] = true
6 遍历这个站临近的站点 l , 然后遍历站点i 与 l 所属的线路 k  我们设nodea j ={ l,k}   这时候我们讨论  设now = top.second
(1) 如果dist[j.first] > dist[now .first] + dp[now.first][j.first]  则更新 ,   pre[j.first] = now;如果大于则 更新 ,并且 pre[j.frist] =  now ; 距离表同样也更新 然后入队列(2) 如果dist[j.first] == dist[now .first] + dp[now.first][j.first]我们需要判断换乘最少!如果k==now.second 说明不需要换乘 我们判断trans[j.first] 是否大于 trans[now.first]即可  如果大于则更新如果k!=now.second 说明需要换乘 我们判断trans[j.first] 是否大于 trans[now.first]+1 即可 如果大于则更新7 最后等待while执行完毕 我们获得了 pre[ endstr ]的信息,然后循环调用pre 直到00结束

最少换乘实现

所需容器

QMap<QString,int> dist; //距离表QMap<QString,int> trans; //换乘QMap<nodea,bool> final; //是否遍历过typedef std::pair<int,int> PII;  //换乘 距离typedef std::pair<QString,QString> nodea; //站点名 和 线路名typedef std::pair<PII,nodea> PLL; // 某个站点的换成次数 和 距离 以及父站点和所属线路QMap<QString,nodea>pre;  //还原最少换乘的工具std::priority_queue<PLL,std::vector<PLL >, std::greater<PLL > > q; //优先队列 优先使用换乘最少的站点

算法思路

算法思路1 将换乘表 和 距离表全部设置为INTMAX2 将起点的 换成表 和 距离表 设置为 0
3 将出发站信息存储到优先队列q中 { {00}{startstr , linename} } 注意(出发点可能有多个,出发点有可能属于多个线路)
4 将pre[startstr]赋值为{ "00","00"} 方便还原路径时截止
5 进入while循环 每次取top值 ,为换乘最少的站 ,判断final[top.second]是否为true,如果已经遍历过 那么continue ,否则 final[top.second] = true
6 遍历这个站临近的站点 l , 然后遍历站点i 与 l 所属的线路 k  我们设nodea j ={ l,k}      这时候我们讨论  设now = top.second
(1)如果站点i的线路 与 k 一样 那么换乘次数不会增加 这个时候我们判断 trans[j.first] 是否大于 trans[i] 如果大于则 更新 ,并且 pre[j.frist] =  now ; 距离表同样也更新 然后入队列如果 换乘次数相等的话  我们判断距离表 , 如果dist[j.first] > dist[now .first] + dp[now.first][j.first]则更新 pre[j.first] = now;(2) 如果站点i的线路 与 k不一样 那么我们的换乘就有可能+1这个时候我们判断trans[j.first]  是否大于 trans[now.frist] +1 如果大于 则更新 并且 pre[j.first] = { now.first,k} ; 距离表同样也更新 这里如果pre[j.frist] = now就会出错,问题在后续讲解如果 transp[j.irst]  == trans[now.first] +1  我们就判断距离表 如果dist[j.first] > dist[now .first] + dp[now.first][j.first] 则更新,pre[j.first] = {now.first,k} 
7 最后等待while执行完毕 我们获得了 pre[ endstr ]的信息,然后循环调用pre 直到00结束

成果展示

在这里插入图片描述

代码实现

判断是最短路径还是最少换乘

void ChooseShortorLessPath(QGraphicsView *graphicsView,QString startstr,QString endstr,QRadioButton *sht,QRadioButton *less,QTextBrowser *textBrowser){qDebug()<<"选择开始\n";if(startstr.size()==0||endstr.size()==0){QMessageBox MyBox(QMessageBox::Warning,"警告","请选择站点",QMessageBox::Yes|QMessageBox::No);MyBox.exec();return;}QMap<QString, node>::iterator it = Station.find(startstr);if (it == Station.end()) {QMessageBox MyBox(QMessageBox::Warning,"警告","输入站点有误",QMessageBox::Yes|QMessageBox::No);MyBox.exec();return;}it =Station.find(endstr);if (it == Station.end()) {QMessageBox MyBox(QMessageBox::Warning,"警告","输入站点有误",QMessageBox::Yes|QMessageBox::No);MyBox.exec();return;}if(startstr == endstr){QMessageBox MyBox(QMessageBox::Warning,"警告","请不要输入相同站点 ",QMessageBox::Yes|QMessageBox::No);MyBox.exec();return;}if(sht->isChecked()) getshortTimePath(graphicsView,startstr,endstr,textBrowser);if(less->isChecked()) getlessTransPath(graphicsView,startstr,endstr,textBrowser);}

最短路径代码实现

typedef std::pair<int,int> PII;
typedef std::pair<QString,QString> nodea;
typedef std::pair<PII,nodea> PLL;void getshortTimePath(QGraphicsView *graphicsView,const QString startstr,const QString endstr,QTextBrowser *textBrowser){qDebug()<<"选择成功\n";const int IntMax = INT32_MAX;QMap<QString,int> dist; //距离表QMap<QString,int> trans; //换乘QMap<nodea,bool> final; //是否遍历过for(auto i:Station.keys()){dist[i] = IntMax;trans[i] = IntMax;}QMap<QString,nodea>pre;pre[startstr] = nodea{"00","00"};std::priority_queue<PLL,std::vector<PLL >, std::greater<PLL > > q;for(auto i:Station_Line[startstr]){q.push(PLL{{0,0},nodea{startstr,i}});}dist[startstr] = 0;trans[startstr] = 0;qDebug()<<"初始化完成\n";while(q.size()){PLL f= q.top();q.pop();nodea now = f.second;if(final[now]) continue;final[now] = true;for(auto i:edge[now.first]){ //相邻的站点for(auto j:mp[now.first][i]){ //和相邻站点共有的线路qDebug()<<now.first<<"-----"<<i<<"----"<<j<<" \n ";nodea newnodea = nodea{i,j};if(final[newnodea]) continue;if(dist[i] > dist[i]+dp[now.first][i]){dist[i] = dist[i]+dp[now.first][i];qDebug()<<now.first<<"---"<<i<<"......."<<dist[i]<<" \n ";if(j == now.second){ trans[i] = trans[now.first];  pre[i] = now; }else {trans[i] = trans[now.first] + 1; pre[i] = nodea{now.first,j}; }qDebug()<<i<<"---"<<pre[i]<<" \n ";q.push(PLL{PII{dist[i],trans[i]},newnodea});}else if(dist[i] == dist[now.first]+dp[now.first][i]){if(j == now.second){if(trans[i] > trans[now.first]){trans[i] = trans[now.first];pre[i] = now;q.push(PLL{PII{dist[i],trans[i]},newnodea});}}if(j != now.second){if(trans[i] > trans[now.first] + 1 ){trans[i] = trans[now.first] + 1;pre[i] = nodea{now.first,j};q.push(PLL{PII{dist[i],trans[i]},newnodea});}}}}}}qDebug()<<"最短路执行完毕\n";QList<nodea>s;int t=0;nodea u = pre[endstr];while(u.second!="00"){s.append(u);qDebug()<<"---"<<u.first<<" \n ";u=pre[u.first];t++;if(t>40) return;}qDebug()<<"还原成功\n";drawpath(graphicsView,startstr,endstr,s,textBrowser);
}

最少换乘代码实现

void getlessTransPath(QGraphicsView *graphicsView ,const QString startstr,const QString endstr,QTextBrowser *textBrowser){qDebug()<<"选择成功\n";const int IntMax = INT32_MAX;QMap<QString,int> dist; //距离表QMap<QString,int> trans; //换乘QMap<nodea,bool> final; //是否遍历过for(auto i:Station.keys()){trans[i] = IntMax;dist[i] = IntMax;}QMap<QString,nodea>pre;pre[startstr] = nodea{"00","00"};std::priority_queue<PLL,std::vector<PLL >, std::greater<PLL > > q;for(auto i:Station_Line[startstr]){q.push(PLL{{0,0},nodea{startstr,i}});}dist[startstr] = 0;trans[startstr] = 0;qDebug()<<"初始化完成\n";while(q.size()){PLL f= q.top();q.pop();nodea now = f.second;if(final[now]) continue;final[now] = true;for(auto i:edge[now.first]){ //相邻的站点for(auto j:mp[now.first][i]){ //和相邻站点共有的线路qDebug()<<now.first<<"-----"<<i<<"----"<<j<<" \n ";nodea newnodea = nodea{i,j};if(final[newnodea]) continue;if(j == now.second){if(trans[i] > trans[now.first]){dist[i] = dist[now.first] + dp[now.first][i];trans[i] = trans[now.first];pre[i] = now;q.push(PLL{PII{trans[i],dist[i]},newnodea});qDebug()<<now.first<<"---"<<i<<"......."<<dist[i]<<" \n ";}else if(trans[i] == trans[now.first]){if(dist[i] > dist[now.first]+dp[now.first][i]){dist[i] = dist[now.first]+dp[now.first][i];qDebug()<<now.first<<"---"<<i<<"......."<<dist[i]<<" \n ";pre[i] = now;q.push(PLL{PII{trans[i],dist[i]},newnodea});}}}if(j != now.second){if(trans[i] > trans[now.first] + 1 ){trans[i] = trans[now.first] + 1;dist[i] = dist[now.first] + dp[now.first][i];pre[i] = nodea{now.first,j};q.push(PLL{PII{trans[i],dist[i]},newnodea});qDebug()<<now.first<<"---"<<i<<"......."<<now<<" \n ";}else if(trans[i] == trans[now.first] + 1 ){if(dist[i] > dist[now.first]+dp[now.first][i]){dist[i] = dist[now.first]+dp[now.first][i];qDebug()<<now.first<<"---"<<i<<"......."<<dist[i]<<" \n ";pre[i] = nodea{now.first,j};q.push(PLL{PII{trans[i],dist[i]},newnodea});}}}}}}qDebug()<<"最短路执行完毕\n";QList<nodea>s;int t=0;nodea u = pre[endstr];while(u.second!="00"){s.append(u);qDebug()<<"---"<<u.first<<" \n ";u=pre[u.first];t++;if(t>40) return;}qDebug()<<"还原成功\n";drawpath(graphicsView,startstr,endstr,s,textBrowser);
}

根据所得List画出线路

void getlessTransPath(QGraphicsView *graphicsView ,const QString startstr,const QString endstr,QTextBrowser *textBrowser){qDebug()<<"选择成功\n";const int IntMax = INT32_MAX;QMap<QString,int> dist; //距离表QMap<QString,int> trans; //换乘QMap<nodea,bool> final; //是否遍历过for(auto i:Station.keys()){trans[i] = IntMax;dist[i] = IntMax;}QMap<QString,nodea>pre;pre[startstr] = nodea{"00","00"};std::priority_queue<PLL,std::vector<PLL >, std::greater<PLL > > q;for(auto i:Station_Line[startstr]){q.push(PLL{{0,0},nodea{startstr,i}});}dist[startstr] = 0;trans[startstr] = 0;qDebug()<<"初始化完成\n";while(q.size()){PLL f= q.top();q.pop();nodea now = f.second;if(final[now]) continue;final[now] = true;for(auto i:edge[now.first]){ //相邻的站点for(auto j:mp[now.first][i]){ //和相邻站点共有的线路qDebug()<<now.first<<"-----"<<i<<"----"<<j<<" \n ";nodea newnodea = nodea{i,j};if(final[newnodea]) continue;if(j == now.second){if(trans[i] > trans[now.first]){dist[i] = dist[now.first] + dp[now.first][i];trans[i] = trans[now.first];pre[i] = now;q.push(PLL{PII{trans[i],dist[i]},newnodea});qDebug()<<now.first<<"---"<<i<<"......."<<dist[i]<<" \n ";}else if(trans[i] == trans[now.first]){if(dist[i] > dist[now.first]+dp[now.first][i]){dist[i] = dist[now.first]+dp[now.first][i];qDebug()<<now.first<<"---"<<i<<"......."<<dist[i]<<" \n ";pre[i] = now;q.push(PLL{PII{trans[i],dist[i]},newnodea});}}}if(j != now.second){if(trans[i] > trans[now.first] + 1 ){trans[i] = trans[now.first] + 1;dist[i] = dist[now.first] + dp[now.first][i];pre[i] = nodea{now.first,j};q.push(PLL{PII{trans[i],dist[i]},newnodea});qDebug()<<now.first<<"---"<<i<<"......."<<now<<" \n ";}else if(trans[i] == trans[now.first] + 1 ){if(dist[i] > dist[now.first]+dp[now.first][i]){dist[i] = dist[now.first]+dp[now.first][i];qDebug()<<now.first<<"---"<<i<<"......."<<dist[i]<<" \n ";pre[i] = nodea{now.first,j};q.push(PLL{PII{trans[i],dist[i]},newnodea});}}}}}}qDebug()<<"最短路执行完毕\n";QList<nodea>s;int t=0;nodea u = pre[endstr];while(u.second!="00"){s.append(u);qDebug()<<"---"<<u.first<<" \n ";u=pre[u.first];t++;if(t>40) return;}qDebug()<<"还原成功\n";drawpath(graphicsView,startstr,endstr,s,textBrowser);
}

ui界面的维护(前提条件)

界面

在这里插入图片描述

初始化combox控件

void initcombox(QComboBox *combox1,QComboBox *combox2){QStringList sta_name_list;for(auto &i:Station.keys())sta_name_list.append(i);std::sort(sta_name_list.begin(),sta_name_list.end(),[](const QString &s1, const QString &s2){return (s1.localeAwareCompare(s2) < 0);});combox1->addItems(sta_name_list);combox2->addItems(sta_name_list);QLineEdit *line1 = new QLineEdit;combox1->setLineEdit(line1);combox1->lineEdit()->clear();QLineEdit *line2 = new QLineEdit;combox2->setLineEdit(line2);combox2->lineEdit()->clear();
}

建立槽函数

connect(ui->pushButton,&QPushButton::clicked,this,[=]{ChooseShortorLessPath(ui->graphicsView,ui->comboBox->lineEdit()->text(),ui->comboBox_2->lineEdit()->text(),ui->radioButton,ui->radioButton_2,ui->textBrowser);});

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/87116.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

84、Redis客户端-->可视化图形界面工具(Another Redis Desktop Manager)的下载、安装及初步使用

Redis客户端–>可视化图形界面工具(Another Redis Desktop Manager)的下载、安装及初步使用 ★ Redis客户端&#xff1a; ▲ Redis自带的命令行工具&#xff08;简陋&#xff09;&#xff1a; CLI工具&#xff0c;重新打开一个命令行窗口&#xff0c;在其中输入如下命令&…

人工智能轨道交通行业周刊-第61期(2023.9.18-9.24)

本期关键词&#xff1a;焊线机器人、智能综合运维管理系统、信号平面图、铁路部门架构、书生浦语大模型 1 整理涉及公众号名单 1.1 行业类 RT轨道交通人民铁道世界轨道交通资讯网铁路信号技术交流北京铁路轨道交通网上榜铁路视点ITS World轨道交通联盟VSTR铁路与城市轨道交通…

uniapp、vue实现滑动拼图验证码

uniapp、vue实现滑动拼图验证码 实际开发工作中&#xff0c;在登陆的时候需要短信验证码&#xff0c;但容易引起爬虫行为&#xff0c;需要用到反爬虫验证码&#xff0c;今天介绍一下拼图验证码&#xff0c;解决验证码反爬虫中的滑动验证码反爬虫。滑动拼图验证码是在滑块验证码…

Android应用线上闪退问题解决

解决Android应用线上闪退问题需要仔细的监控、调试和分析。以下是一些解决Android线上闪退问题的工具和方法&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 工具&#xff1a; 1.Google Play 控制台&…

Mysql安装

一、Mysql官网下载安装 MySQL :: Download MySQL Community Server下载 二、安装 下载后打开文件进行安装&#xff1a; 选择custom自定义 选择后带点击Execute 接着下一步 设置密码&#xff0c;下一步 全好后点击finish 之后继续下一步&#xff0c;finish

怎样防止员工泄露技术?(十条避免公司泄密的措施)

在当今信息化社会&#xff0c;公司信息的安全性和保密性显得尤为重要。一旦公司信息泄露&#xff0c;不仅会对公司的经营造成严重影响&#xff0c;还可能引发法律纠纷。因此&#xff0c;采取有效的措施来防止公司信息泄露是非常必要的。以下是一些具体的措施&#xff1a; 部署洞…

数据结构之【泛型】

泛型&#xff1a;定义阶段不明确具体类型&#xff0c;产生对象时明确具体类型。 //Object是Java中的最高参数统一化&#xff0c;能够接受所有的引用类型&#xff1b; //有了包装类的自动拆装箱之后&#xff0c;Object还能够接收基本类型数值&#xff08;自动装箱&#xff09; …

入门级制作电子期刊的网站推荐

随着数字化时代的到来&#xff0c;越来越多的人开始尝试制作自己的电子期刊。如果你也是其中的一员&#xff0c;那么这篇文章可以帮助你制作电子期刊。无论是初学者还是有一定经验的制作者&#xff0c;都能快速完成高质量的电子期刊制作 小编经常使用的工具是-----FLBOOK在线制…

修改vscode底部栏背景和字体颜色

修改vscode底部栏背景和字体颜色 如图&#xff1a; 首先打开齿轮&#xff0c;打开设置搜索workbench.colorCustomizations,然后点击编辑setting.json修改setting.json内内容 "workbench.colorCustomizations": {"statusBar.foreground": "#FFFFFF…

【C++】C++的类型转换

C的类型转换 一、C语言中的类型转换二、C的类型转换1、static_cast2、reinterpret_cast3、const_cast4、dynamic_cast 三、RTTI 一、C语言中的类型转换 在C语言中&#xff0c;如果赋值运算符左右两侧类型不同&#xff0c;或者形参与实参类型不匹配&#xff0c;或者返回值类型与…

【力扣每日一题】2023.9.23 树上的操作

目录 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 代码&#xff1a; 题目&#xff1a; 示例&#xff1a; 分析&#xff1a; 这是一道程序设计类的题目&#xff0c;题目比较长&#xff0c;我稍微概括一下。 构造函数中给我们一个数组&#xff0c;第i个元素表示第…

3D目标检测实战 | 图解KITTI数据集与数据格式

目录 1 数据集简介2 传感器坐标系3 数据集下载与组织4 数据内容说明4.1 矫正文件calib4.2 图像文件image4.3 点云文件velodyne4.4 标签文件label4.5 平面文件plane 1 数据集简介 KITTI数据集是一个广泛应用于自动驾驶和计算机视觉领域的公开数据集。该数据集由德国卡尔斯鲁厄理…

牛客java训练题 day1

9.24 day1 Q 1. this 指针是用来干什么的&#xff1f; 2.基类和派生类分别是指什么&#xff1f; 3.为什么方法中不能写静态变量 4. 解释一下ASCII码和ANSI码和两者的区别 5.简述j ava.io java.sql java.awt java.rmi 分别是什么类型的包 6. 看下面一段代码&#xff1a;…

Ubuntu安装RabbitMQ server - 在外远程访问

文章目录 前言1.安装erlang 语言2.安装rabbitMQ3. 内网穿透3.1 安装cpolar内网穿透(支持一键自动安装脚本)3.2 创建HTTP隧道 4. 公网远程连接5.固定公网TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网TCP端口地址 前言 RabbitMQ是一个在 AMQP(高级消息队列协议)基…

安装OpenSearch

title: “安装opensearch” createTime: 2021-11-30T19:13:4508:00 updateTime: 2021-11-30T19:13:4508:00 draft: false author: “name” tags: [“es”,“安装”] categories: [“OpenSearch”] description: “测试的” 说明 基于Elasticsearch7.10.2 的 opensearch-1.1.…

使用QLoRA对Llama 2进行微调的详细笔记

使用QLoRA对Llama 2进行微调是我们常用的一个方法&#xff0c;但是在微调时会遇到各种各样的问题&#xff0c;所以在本文中&#xff0c;将尝试以详细注释的方式给出一些常见问题的答案。这些问题是特定于代码的&#xff0c;大多数注释都是针对所涉及的开源库以及所使用的方法和…

【工作记录】springboot集成aop实现日志@20230918

springboot集成aop实现日志 1. 添加依赖 <!-- aop 依赖 --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId> </dependency>2. 定义注解 Target(ElementType.METHOD)…

windows 安装 MySQL 绿色版

windows 安装 MySQL 绿色版 下载 官网&#xff1a; MySQL下载页面&#xff1a; MySQL直接下载链接&#xff1a;https://cdn.mysql.com//Downloads/MySQL-8.0/mysql-8.0.34-winx64.zip 安装 将下载的mysql.zip文件解压缩到指定目录 搜索 cmd 并以管理员身份运行 切换到…

【微信小程序开发】宠物预约医疗项目实战-注册实现

【微信小程序开发】宠物预约医疗项目实战-注册实现 第二章 宠物预约医疗项目实战-注册实现 文章目录 【微信小程序开发】宠物预约医疗项目实战-注册实现前言一、打开项目文件二、编写wxss代码2.1 什么是wxss2.2 配置主程序全局样式 三. 在sign文件下的wxml文件中编写如下代码并…

数字森林:无人机航测技术在林业调查中的应用

林业调查是林业工作的基础&#xff0c;对于森林资源的管理、规划、保护、经济发展和农业种植等方面都具有重要的意义。传统林业调查主要依赖人工进行&#xff0c;存在工作效率低、数据精度低、数据分析困难、受地形限制、无法实时监测等缺陷。 随着科技的不断发展&#xff0c;无…