数据结构-最短路径问题

一.问题分类

二.无权图单源最短路算法

dist[]数组记录的是个个顶点到源点的距离这个数组的下标表示顶点

源点到自己的距离是0,dist[s]=0

path[]数组记录的是这个顶点的前驱,可以同过这个数组找到源点到个个顶点的距离

代码如下

void Unweighted(MGraph Graph, Vertex S) {Vertex V,W;dist[S] = 0;//初始化源点到自己的距离queue<Vertex>q;q.push(S);//压栈while(!q.empty()) {/*弹栈*/V = q.front();q.pop();for (W = 0; W < Graph->Nv; W++) {/*点W到源点的距离没有被确定并且两个顶点有边,*/if (dist[W] == -1 && IsEdge(Graph, V, W) ){dist[W] = dist[V] + 1;/*更新距离*/path[W] = V;//记录W的前驱q.push(W);}}}
}

dist[]和path[]都初始为-1

全部代码

#include<iostream>
#include<queue>
using namespace std;
#define INIFIN 65535/*表示没有边*/
#define MaxVertenNum 100/*最大顶点值*/
typedef int Vertex;/*顶点的下标用整形表示*/
typedef int WeightType;/*权重*/
int dist[MaxVertenNum], path[MaxVertenNum];
/* 边的定义*/
typedef struct ENode* PtrToENode;
struct ENode
{Vertex V1, V2;/*有向图<v1,v2>*///WeightType Weight;/*权重*/
};
typedef PtrToENode Edge;//图的定义
typedef struct GNode* PtrToGNode;
struct GNode {int Nv;/*顶点个数*/int Ne;/*边的个数*/WeightType G[MaxVertenNum][MaxVertenNum];
};
typedef PtrToGNode MGraph;MGraph CreateGraph(int VerNum) {/*创建1个VN个顶点0条边的图*/Vertex V, W;MGraph Graph = new GNode();Graph->Nv = VerNum;Graph->Ne = 0;for (V = 0; V < Graph->Nv; V++)for (W = 0; W < Graph->Nv; W++)Graph->G[V][W] = INIFIN;return Graph;
}
//插入边
void InsertEdge(MGraph Graph, Edge E)
{/* 插入边 <V1, V2> */Graph->G[E->V1][E->V2] = 1;/* 若是无向图,还要插入边<V2, V1> *///Graph->G[E->V2][E->V1] = 1;  
}MGraph BuildGraph() {Edge E;MGraph Graph;Vertex Nv;cin >> Nv;/*顶点个数*/Graph = CreateGraph(Nv);cin >> Graph->Ne;/*输入边的个数*/if (Graph->Ne != 0) {for (int i = 0; i < Graph->Ne; i++) {E = new ENode();cin >> E->V1 >> E->V2;InsertEdge(Graph, E);}}return Graph;
}
bool IsEdge(MGraph G, Vertex v1, Vertex v2) {return G->G[v1][v2] < INIFIN ? true : false;
}
void Unweighted(MGraph Graph, Vertex S) {Vertex V,W;dist[S] = 0;//初始化源点到自己的距离queue<Vertex>q;q.push(S);//压栈while(!q.empty()) {/*弹栈*/V = q.front();q.pop();for (W = 0; W < Graph->Nv; W++) {/*点W到源点的距离没有被确定并且两个顶点有边,*/if (dist[W] == -1 && IsEdge(Graph, V, W) ){dist[W] = dist[V] + 1;/*更新距离*/path[W] = V;//记录W的前驱q.push(W);}}}
}
void FindDp(int V) {if (V == -1)return;FindDp(path[V]);cout << V << " ";}
int main()
{MGraph G = BuildGraph();for (int i = 0; i < MaxVertenNum; i++) {dist[i] = path[i] = -1;}Unweighted(G, 0);cout << "请输入终点顶点:";int n;cin >> n;cout << "源点到终点的路径:";FindDp(n);cout << endl;system("pause");return 0;
}
/*
7
12
0 1
0 3
1 3
1 4
2 0
2 5
3 2
3 4
3 5
3 6
4 6
6 5
*/

运行结果

三.有权图单源最短路算法

S集合存储的是的已经确定最短距离的顶点,起初集合只有一个顶点源点

若顶点V没有收录到集合,dist[V]表示源点到顶点V的距离,但这个距离不是真正的最短路径,当V顶点被收录到集合的时候,dist[V]才是最短距离

每次从dist[]中找到距离最短的顶点

当有顶点加入到集合中的时候,可能会影响dits[W]的值,及顶点的邻接点

代码如下

Vertex FindMinDist(MGraph Graph) {/*返回未被收入顶点中的最小dist者*/Vertex MinV, V;int MinDist = INFINITY;for (V = 0; V < Graph->Nv; V++) {if (Visted[V] == false && dist[V] < MinDist) {/*若V未被收录,且dist[V]更小*/MinDist = dist[V];/*更新最小距离*/MinV = V;/*更新最小顶点*/}}if (MinDist < INFINITY)/*若找到最小dist*/return MinV;/*返回对应的顶点下标*/else return 0;/*若这样的顶点不存在,返回错误标记*/
}
bool Dijkstra(MGraph Graph, Vertex S) {Vertex V, W;/*初始化:此处默认邻接矩阵中不存在的边用INFINITY表示*/for (V = 0; V < Graph->Nv; V++) {dist[V] = Graph->G[S][V];//与S结点邻接把边值放到dist中if (dist[V] < INFINITY)//有边记录它的前驱path[V] = S; //记录V的前驱V的前驱是Selsepath[V] = -1;Visted[V] = false;//全部顶点都没有收录}/*先将收起点收入集合*/dist[S] = 0;Visted[S] = true;//放到集合中while (1) {/*找到未被收入顶点中dist最小者*/V = FindMinDist(Graph);if (!V)/*如不存在*/break;//算法结束Visted[V] = true;//收录Vfor (W = 0; W < Graph->Nv; W++)if (Visted[W] == false && Graph->G[V][W] < INFINITY) {if (Graph->G[V][W] < 0)//若有负边return false;//if (dist[V] + Graph->G[V][W] < dist[W]) {dist[W] = dist[V] + Graph->G[V][W];path[W] = V;//跟新S到W的路径}}}return true;
}

全部代码

#include<iostream>
using namespace std;
#define INFINITY 65535/*设为最大值*/
#define MaxVertexNum 100 /*最大顶点树设为100*/
typedef int Vertex; /*用顶点下标表示为整型*/
typedef int WeightType;/*边的权值设为整型*/
typedef char DataType;/*顶点存储的数据类型设为字符型*/int Visted[MaxVertexNum];//集合等于false的都属于未被找的最短路径的结点
int dist[MaxVertexNum];//路径长度//
int path[MaxVertexNum];/*边的定义*/
typedef struct ENode* PtrToENode;
struct ENode {Vertex V1, V2;/*有向边<v1,v2>*/WeightType Weight;/*权重 */}; typedef PtrToENode Edge;/*图的定义*/
typedef struct GNode* PtrToGNode;
struct GNode
{int Nv;/*顶点个数*/int Ne;/*边的个数*/WeightType G[MaxVertexNum][MaxVertexNum];
};
typedef PtrToGNode MGraph;/*以邻接矩阵存储的图的类型*/MGraph CreateGraph(int VertexNum) {/*初始化一个有VN个顶点但没有边的图*/Vertex V, W;MGraph Graph;Graph = new GNode();Graph->Nv = VertexNum;Graph->Ne = 0;/*初始化邻接矩阵*/for (V = 0; V < Graph->Nv; V++)for (W = 0; W < Graph->Nv; W++)Graph->G[V][W] = INFINITY;return Graph;
}
void Insert(MGraph Graph, Edge E) {Graph->G[E->V1][E->V2] = E->Weight;
}
bool IsEdge(MGraph Graph, Vertex V, Vertex W) {return Graph->G[V][W] < INFINITY ? true : false;
}
/*邻接矩阵存储*/Vertex FindMinDist(MGraph Graph) {/*返回未被收入顶点中的最小dist者*/Vertex MinV, V;int MinDist = INFINITY;for (V = 0; V < Graph->Nv; V++) {if (Visted[V] == false && dist[V] < MinDist) {/*若V未被收录,且dist[V]更小*/MinDist = dist[V];/*更新最小距离*/MinV = V;/*更新最小顶点*/}}if (MinDist < INFINITY)/*若找到最小dist*/return MinV;/*返回对应的顶点下标*/else return 0;/*若这样的顶点不存在,返回错误标记*/
}
bool Dijkstra(MGraph Graph, Vertex S) {Vertex V, W;/*初始化:此处默认邻接矩阵中不存在的边用INFINITY表示*/for (V = 0; V < Graph->Nv; V++) {dist[V] = Graph->G[S][V];//与S结点邻接把边值放到dist中if (dist[V] < INFINITY)//有边记录它的前驱path[V] = S; //记录V的前驱V的前驱是Selsepath[V] = -1;Visted[V] = false;//全部顶点都没有收录}/*先将收起点收入集合*/dist[S] = 0;Visted[S] = true;//放到集合中while (1) {/*找到未被收入顶点中dist最小者*/V = FindMinDist(Graph);if (!V)/*如不存在*/break;//算法结束Visted[V] = true;//收录Vfor (W = 0; W < Graph->Nv; W++)if (Visted[W] == false && Graph->G[V][W] < INFINITY) {if (Graph->G[V][W] < 0)//若有负边return false;//if (dist[V] + Graph->G[V][W] < dist[W]) {dist[W] = dist[V] + Graph->G[V][W];path[W] = V;//跟新S到W的路径}}}return true;
}
void FindDp(int V) {if (V == -1)return;FindDp(path[V]);cout << V << endl;}
int main()
{MGraph Graph = CreateGraph(7);Graph->Ne = 12;Vertex a[12] = { 0,0,1,1,2,2,3,3,3,3,4,6 };Vertex b[12] = { 1,3,3,4,0,5,2,4,5,6,6,5 };WeightType w[12] = { 2,1,3,10,4,5,2,2,8,4,6,1 };/* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */for (int i = 0; i < Graph->Ne; i++) {Edge E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */E->V1 = a[i]; E->V2 = b[i]; E->Weight = w[i];/* 注意:如果权重不是整型,Weight的读入格式要改 */Insert(Graph, E);}for (int i = 0; i < MaxVertexNum; i++) { Visted[i] = false; dist[i] = INFINITY; path[i] = -1; }Dijkstra(Graph, 0);int n;cin >> n;FindDp(n);return 0;
}

运行结果

四.多源最短路算法

D^k[i][j]表示i到j经过k的最小长度

依次将每个点作为中间点去做更新

k=V-1是D[i][j]将最小路径更新完成

bool Floyd(MGraph Graph) {for(int i=0;i<Graph->Nv;i++)for (int j = 0; j < Graph->Nv; j++) {D[i][j] = Graph->G[i][j];path[i][j] = -1;}/*k表示中间点*/for(int k=0;k<Graph->Nv;k++)for (int i = 0; i < Graph->Nv; i++)for (int j = 0; j < Graph->Nv; j++)if (D[i][k] + D[k][j] < D[i][j]) {D[i][j] = D[i][k] + D[k][j];if (i == j && D[i][j] < 0)/*若出现负边无法解决*/return false;path[i][j] = k;}return true;
}

全部代码

#include<iostream>
using namespace std;
#define MaxvertexNum 100/*最大顶点值*/
#define INF 65535/*无穷大表示没有边直接相连*/
typedef int Vertex;/*顶点下标*/
typedef int WeightType;/*权重*/
WeightType D[MaxvertexNum][MaxvertexNum];/*D[i][j],顶点i到顶点j的最短距离*/
Vertex path[MaxvertexNum][MaxvertexNum];/*记录路径*//*边的定义*/
typedef struct ENode* PtrToENode;
struct ENode
{Vertex V1, V2;WeightType Weigtht;
};
typedef PtrToENode Edge;/*图的定义*/
typedef struct GNode* PtrToGNode;
struct GNode {int Nv;/*顶点个数*/int Ne; /*边的个数*/WeightType G[MaxvertexNum][MaxvertexNum];
};
typedef PtrToGNode MGraph;MGraph CreateGraph(int Vertexnum) {MGraph G = new GNode();G->Nv = Vertexnum;G->Ne = 0;for (int i = 0; i < G->Nv; i++)for (int j = 0; j < G->Nv; j++)G->G[i][j] = INF;return G;
}
void InsertEdeg(MGraph Graph, Edge E) {Graph->G[E->V1][E->V2] = E->Weigtht;Graph->G[E->V2][E->V1] = E->Weigtht;
}bool Floyd(MGraph Graph) {for(int i=0;i<Graph->Nv;i++)for (int j = 0; j < Graph->Nv; j++) {D[i][j] = Graph->G[i][j];path[i][j] = -1;}/*k表示中间点*/for(int k=0;k<Graph->Nv;k++)for (int i = 0; i < Graph->Nv; i++)for (int j = 0; j < Graph->Nv; j++)if (D[i][k] + D[k][j] < D[i][j]) {D[i][j] = D[i][k] + D[k][j];if (i == j && D[i][j] < 0)/*若出现负边无法解决*/return false;path[i][j] = k;}return true;
}
//void FindDp(int i, int j) {
//	if (path[i][j] == -1)
//		return;
//	FindDp(i, path[i][j]);
//	cout << j;
//}
MGraph BuildGraph() {Edge E;MGraph Graph;Vertex Nv;cin >> Nv;/*顶点个数*/Graph = CreateGraph(Nv);cin >> Graph->Ne;/*输入边的个数*/if (Graph->Ne != 0) {for (int i = 0; i < Graph->Ne; i++) {E = new ENode();cin >> E->V1 >> E->V2>>E->Weigtht;E->V1--;E->V2--;InsertEdeg(Graph, E);}}return Graph;
}
int main()
{MGraph Graph = BuildGraph();Floyd(Graph);int i,j;
//	cin >> i>>j;
//	FindDp(i,j);return 0;
}

 怎么样打印两点之间的路径还没有写好

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

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

相关文章

Vue.js 实现用户注册功能

在本篇博客中&#xff0c;我们将通过一个简单的例子来展示如何使用 Vue.js 来实现一个用户注册功能。我们将创建一个包含用户名、邮箱和密码输入的表单&#xff0c;并在用户点击“创建账号”按钮时进行简单的验证。 完整代码 <!DOCTYPE html> <html lang"en&q…

【Java 学习】面向程序的三大特性:封装、继承、多态

引言 1. 封装1.1 什么是封装呢&#xff1f;1.2 访问限定符1.3 使用封装 2. 继承2.1 为什么要有继承&#xff1f;2.2 继承的概念2.3 继承的语法2.4 访问父类成员2.4.1 子类中访问父类成员的变量2.4.2 访问父类的成员方法 2.5 super关键字2.6 子类的构造方法 3. 多态3.1 多态的概…

impala入门与实践

1.impala基本介绍 impala是cloudera提供的一款高效率的sql查询工具&#xff0c;提供实时的查询效果&#xff0c;官方测试性能比hive快10到100倍&#xff0c;其sql查询比sparkSQL还要更加快速&#xff0c;号称是当前大数据领域最快的查询sql工具。impala是参照谷歌的新三篇论文…

结构方程模型(SEM)入门到精通:lavaan VS piecewiseSEM、全局估计/局域估计;潜变量分析、复合变量分析、贝叶斯SEM在生态学领域应用

目录 第一章 夯实基础 R/Rstudio简介及入门 第二章 结构方程模型&#xff08;SEM&#xff09;介绍 第三章 R语言SEM分析入门&#xff1a;lavaan VS piecewiseSEM 第四章 SEM全局估计&#xff08;lavaan&#xff09;在生态学领域高阶应用 第五章 SEM潜变量分析在生态学领域…

小米PC电脑手机互联互通,小米妙享,小米电脑管家,老款小米笔记本怎么使用,其他品牌笔记本怎么使用,一分钟教会你

说在前面 之前我们体验过妙享中心&#xff0c;里面就有互联互通的全部能力&#xff0c;现在有了小米电脑管家&#xff0c;老款的笔记本竟然用不了&#xff0c;也可以理解&#xff0c;毕竟老款笔记本做系统研发的时候没有预留适配的文件补丁&#xff0c;至于其他品牌的winPC小米…

python爬虫案例——猫眼电影数据抓取之字体解密,多套字体文件解密方法(20)

文章目录 1、任务目标2、网站分析3、代码编写1、任务目标 目标网站:猫眼电影(https://www.maoyan.com/films?showType=2) 要求:抓取该网站下,所有即将上映电影的预约人数,保证能够获取到实时更新的内容;如下: 2、网站分析 进入目标网站,打开开发者模式,经过分析,我…

一分钟食用前端测试框架Jest

安装 其实食用Jest是很简单的,我们只需要安装Jest即可 npm install --save-dev jestyarn add --dev jestpnpm add --save-dev jest ESmodule 本身来说,Jest是不支持Esmodule的,他支持CommonJS,我们需要Babel改一下 npm i --save-dev babel-jest babel/core babel/preset-env …

从 App Search 到 Elasticsearch — 挖掘搜索的未来

作者&#xff1a;来自 Elastic Nick Chow App Search 将在 9.0 版本中停用&#xff0c;但 Elasticsearch 拥有你构建强大的 AI 搜索体验所需的一切。以下是你需要了解的内容。 生成式人工智能的最新进展正在改变用户行为&#xff0c;激励开发人员创造更具活力、更直观、更引人入…

若依框架部署在网站一个子目录下(/admin)问题(

部署在子目录下首先修改vue.config.js文件&#xff1a; 问题一&#xff1a;登陆之后跳转到了404页面问题&#xff0c;解决办法如下&#xff1a; src/router/index.js 把404页面直接变成了首页&#xff08;大佬有啥优雅的解决办法求告知&#xff09; 问题二&#xff1a;退出登录…

【贪心算法第六弹——334.递增的三元子序列(easy)】

目录 1.题目解析 题目来源 测试用例 2.算法原理 3.实战代码 代码解析 本题属于最长递增子序列的简化版本&#xff0c;只需要判断能不能组成三位的递增子序列即可&#xff0c;建议先去看博主的另一篇博客可以更好的理解本篇博客&#xff1a;300.最长递增子序列 1.题目解析…

《TCP/IP网络编程》学习笔记 | Chapter 16:关于 I/O 流分离的其他内容

《TCP/IP网络编程》学习笔记 | Chapter 16&#xff1a;关于 I/O 流分离的其他内容 《TCP/IP网络编程》学习笔记 | Chapter 16&#xff1a;关于 I/O 流分离的其他内容分离 I/O 流2 次 I/O 流分离分离「流」的好处「流」分离带来的 EOF 问题 文件描述符的的复制和半关闭终止「流」…

LeetCode数组题

参考链接 代码随想录 讲解视频链接 数组题 1、(两数之和)给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。你可以假设每种输入只会对应一个答案&#xff0c;并且你不能使用…

Unity-Lightmap入门篇

&#xff1a;&#xff1a;这是一个实战文章&#xff0c;并没有知识分享&#xff0c;或理论知识&#xff1b;完全没有 关键字&#xff1a; “lightmap","全局光照”&#xff0c;“light Probe" (会混合一些中英文搜索&#xff0c;或者全英文搜索&#xff09; …

海康VsionMaster学习笔记(学习工具+思路)

一、前言 VisionMaster算法平台集成机器视觉多种算法组件&#xff0c;适用多种应用场景&#xff0c;可快速组合算法&#xff0c;实现对工件或被测物的查找测量与缺陷检测等。VM算法平台依托海康威视在图像领域多年的技术积淀&#xff0c;自带强大的视觉分析工具库&#xff0c;可…

Python双向链表、循环链表、栈

一、双向链表 1.作用 双向链表也叫双面链表。 对于单向链表而言。只能通过头节点或者第一个节点出发&#xff0c;单向的访问后继节点&#xff0c;每个节点只能记录其后继节点的信息&#xff08;位置&#xff09;&#xff0c;不能向前遍历。 所以引入双向链表&#xff0c;双…

【数据结构笔记】习题

渐进分析 【2010-THU-Mid】f(n) O(g(n))&#xff0c;当且仅当g(n) Ω(f(n))。&#xff08;√&#xff09; 【2010-THU-Mid】若f(n) O(n^2)且g(n) O(n)&#xff0c;则以下结论正确的是&#xff08;AD&#xff09; A. f(n) g(n) O(n^2) B. f(n) / g(n) O(n) C. g(n) O(f(…

ES实用面试题

一、es是什么&#xff0c;为什么要用它&#xff1f; ES通常是Elasticsearch的简称&#xff0c;它是一个基于Lucene构建的开源搜索引擎。Elasticsearch以其分布式、高扩展性和实时数据分析能力而闻名&#xff0c;广泛用于全文搜索、日志分析、实时监控等多种场景。 基本特点&am…

适用于学校、医院等低压用电场所的智能安全配电装置

引言 电力&#xff0c;作为一种清洁且高效的能源&#xff0c;极大地促进了现代生活的便捷与舒适。然而&#xff0c;与此同时&#xff0c;因使用不当或维护缺失等问题&#xff0c;漏电、触电事件以及电气火灾频发&#xff0c;对人们的生命安全和财产安全构成了严重威胁&#xf…

智能桥梁安全运行监测系统守护桥梁安全卫士

一、方案背景 桥梁作为交通基础设施中不可或缺的重要组成部分&#xff0c;其安全稳定的运行直接关联到广大人民群众的生命财产安全以及整个社会的稳定与和谐。桥梁不仅是连接两地的通道&#xff0c;更是经济发展和社会进步的重要纽带。为了确保桥梁的安全运行&#xff0c;桥梁安…

【Python爬虫五十个小案例】爬取豆瓣电影Top250

博客主页&#xff1a;小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介&#xff1a;分享五十个Python爬虫小案例 &#x1fab2;前言 在这篇博客中&#xff0c;我们将学习如何使用Python爬取豆瓣电影Top250的数据。我们将使用requests库来发送HTTP请求&#xff0c;…