六、最短路径——迪杰斯特拉(Dijkstra)算法
在网图和非网图中,最短路径的含义是不同的。由于非网图它没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径;而对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点。显然,我们研究网图更有实际意义,就地图来说,距离就是两顶点间的权值之和。而非网图完全可以理解为所有的边的权值都为1的网。
迪杰斯特拉是一个按路径长度递增的次序产生最短路径的算法。它的思路大体是这样的。
比如说要求下图中顶点v0到顶点v1的最短距离,没有比这更简单的了,答案就是1,路径就是直接vo连线到v1。
由于顶点v1还与v2、v3、v4连线,所以此时我们同时求得了vo→v1→v2=1+3=4,
v0→v1→v3=1+7=8,v0→v1→v4=1+5=6。
现在,我问v0到v2的最短距离,如果你不假思索地说是5,那就犯错了。因为边上都有权值,刚才已经有v0→v1→v2的结果是4,比5还要小1个单位,它才是最短距离。
由于顶点v2还与v4、v5连线,所以此时我们同时求得了v0→v2→v4其实就是v0→v1→v2→v4=4+1=5。这里v0→v2我们用的是刚才计算出来的较小的4。此时我们也发现v0→v1→v2→v4=5要比vo→v1→v4=6还要小。所以vo到v4目前的最小距离是5。
当我们要求v0到v3的最短距离时,通向v3的三条边,除了v6没有研究过外,
v0→v1→v3的结果是8,而v0→v4→v3=5+2=7。因此,v0到v3的最短距离是7。
好了,我想你大致明白,这个迪杰斯特拉(Dijkstra)算法是如何干活的了。它并不是一下子就求出了v0到v8的最短路径,而是一步步求出它们之间顶点的最短路径,过程中都是基于已经求出的最短路径的基础上,求得更远顶点的最短路径,最终得到你要的结果。
现有如下一个网,和它的邻接矩阵
现在我们看一下如何求出v0到v8的最短路径
#include<iostream>
#include<vector>
#include<queue>
using namespace std;#define MAXVEX 100//最大顶点数
typedef char VertexType;//顶点类型
typedef int EdgeType;//边上的权值类型
typedef struct
{VertexType vexs[MAXVEX];//顶点表EdgeType arc[MAXVEX][MAXVEX];//邻接矩阵int numVertexte;//当前顶点数int numEdges;//当前边数
}MGraph;void ShortestPath_Dijkstra(MGraph G, int v0, vector<int>& P, vector<int>& D)
{//P[i]的值为顶点i的前驱顶点//D[i]的值为v0到i的最短路径长度和vector<int> final(G.numVertexte);//final[i]=1表示已求得顶点v0到顶点i的最短路径for (int i = 0; i < G.numVertexte; ++i)//初始化数据{final[i] = 0;//全部初始化为未知最短路径状态P[i] = 0;D[i] = G.arc[v0][i];}D[v0] = 0;//v0至v0的路径为0final[v0] = 1;//v0至v0不需要求路径/*开始主循环,每次求得v0到某个顶点的最短路径*/for (int i = 1; i < G.numVertexte; ++i){int min = INT_MAX;//当前所知离v0顶点的最近距离int k;for (int w = 0; w < G.numVertexte; ++w)//寻找离v0最近的顶点{if (!final[w] && D[w] < min)//如果顶点w为加入最短路径,且v0到w的距离小于之前的min{k = w;min = D[w];}}final[k] = 1;//将目前找到的最近的顶点加入最短路径for (int w = 0; w < G.numVertexte; ++w)//修正当前最短路径及距离{/*此时的min就是前面找到的离v0顶点的最近距离,也就是v0~k的距离*/if (!final[w] && (min + G.arc[k][w] < D[w])){//如果顶点w还没加入最短路径且从v0->k->w的距离 小于 直接从v0->w的距离D[w] = min + G.arc[k][w];//那么就更新v0->w的距离为 v0->k->w的距离P[w] = k;//那么顶点w的前驱顶点就是k}}}
}
final数组是为了v0到某顶点是否已经求得最短路径的标记,如果v0到vi已经有结果,则final[i]=1。
最终的结果
其实最终返回的数组D和数组P,是可以得到v0到任意一个顶点的最短路径和路径长度的。例如v0到v8的最短路径并没有经过v5,但我们已经知道v0到v5的最短路径了。由D[5]=8可知它的路径长度为8,由P[5]=4可知v5的前驱顶点是v4,所以v0到v5的最短路径是V0→V1→V2→V4→V5。
也就是说,我们通过迪杰斯特拉(Dijkstra)算法解决了从某个源点到其余各顶点的最短路径问题。从循环嵌套可以很容易得到此算法的时间复杂度为,尽管有同学觉得,可不可以只找到从源点到某一个特定终点的最短路径,其实这个问题和求源点到其他所有顶点的最短路径一样复杂,时间复杂度依然是。
这就好比,你吃了七个包子终于算是吃饱了,就感觉很不划算,前六个包子白吃了,应该直接吃第七个包子,于是你就去寻找可以吃一个就能饱肚子的包子,能够满足你的要求最终结果只能有一个,那就是用七个包子的面粉和馅做的一个大包子。这种只关注结果而忽略过程的思想是非常不可取的。
可如果我们还需要知道如v3到v5、v1到v7这样的任一顶点到其余所有顶点的最短路径怎么办呢?此时简单的办法就是对每个顶点当作源点运行一次迪杰斯特拉(Dijkstra)算法,等于在原有算法的基础上,再来一次循环,此时整个算法的时间复杂度就成了。
六、最短路径——迪杰斯特拉(Dijkstra)算法相关推荐
- 最短路径 - 迪杰斯特拉(Dijkstra)算法
对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd ...
- 数据结构与算法(7-4)最短路径(迪杰斯特拉(Dijkstra)算法、弗洛伊德(Floyd)算法)
目录 一.最短路径概念 二.迪杰斯特拉(Dijkstra)算法(单源最短路径) 1.原理 2.过程 3.代码 三.弗洛伊德(Floyd)算法(多源最短路径) 1.原理 2.存储 3.遍历 4.代码 参 ...
- 059.迪杰斯特拉(Dijkstra)算法的原理以及解决最短路径问题
1. 迪杰斯特拉(Dijkstra)算法的原理 1.1. 算法应用场景-最短路径问题 1.2. 基本介绍 1.3. 步骤详解 1.4. 思路解析 1.5. 图解步骤 2. 迪杰斯特拉(Dijkstra ...
- 迪杰斯特拉(Dijkstra)算法解决最短路径问题
Dijkstra 算法介绍 迪杰斯特拉算法(Dijkstra)是由荷兰计算机科学家狄克斯特拉于1959年提出的,因此又叫狄克斯特拉算法.迪杰斯特拉(Dijkstra)算法是最经典的最短路径算法之一,用 ...
- c语言迪杰斯特拉算法求最短路径,迪杰斯特拉 ( Dijkstra ) 最短路径算法
迪杰斯特拉算法介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径.它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本 ...
- 最短路径算法-迪杰斯特拉(Dijkstra)算法
最短路径算法-迪杰斯特拉(Dijkstra)算法 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思 ...
- java数据结构和算法——迪杰斯特拉(Dijkstra)算法
目录 一.迪杰斯特拉(Dijkstra)算法介绍 二.迪杰斯特拉(Dijkstra)算法过程 三.迪杰斯特拉(Dijkstra)算法--应用场景(最短路径问题) 四.迪杰斯特拉(Dijkstra)算法 ...
- Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法
1.Java迪杰斯特拉(Dijkstra)算法与弗洛伊德(Floyd)算法 1.1 迪杰斯特拉(Dijkstra)算法 1.1.1 迪杰斯特拉(Dijkstra)算法介绍 迪杰斯特拉(Dijkstra ...
- 数据结构——图——迪杰斯特拉(Dijkstra )算法
数据结构--图--迪杰斯特拉(Dijkstra )算法 这是一个按路径长度递增的次序产生最短路径的算法.它的思路大体是这样的. 比如说要求图7-7-3中顶点v0到顶点v1的最短距离,没有比这更简单的了 ...
- 【图】最短路径--迪杰斯特拉(Dijkdtra)算法
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 算法思想 每次找到离源 ...
最新文章
- matlab simulink 直线一级倒立摆控制方法研究 状态观测
- 【ionic App问题总结系列】ionic 如何更新app版本
- Failed to connect to 127.0.0.1:27017, reason: errno:111 Connection refused(MongoDB启动异常)
- Joomla2.5 JDate 时区日期运算
- JavaScript的面向对象特性
- try catch线程问题???
- 最新emlog程序仿小刀模板源码
- 1.8 为什么是人的表现
- BackgroundWorker的使用
- python3中filter、map、reduce、apply、zip函数用法总结
- python2中的print语句可以不用小括号。_Python基础语法 | 代码规范amp;判断语句amp;循环语句...
- tp1900芯片对比7621a_MT7621A和MT7620A两个芯片各有什么特点?
- 耳机插在的电脑上没有声音
- wpf,silverlight,wp7,winform等学习资料整合(一)
- PUBWIN密码攻防战 打造永攻不破的密码!(转)
- COCOS-BCX|区块链项目介绍
- 用js做一个鼠标惯性动画
- 仓库是时候实施物联网了吗
- svn中项目管理中ec_SVN的项目管理
- 佳能Canon PIXMA MG6851 一体机驱动