最短路径之迪杰斯特拉(Dijkstra)算法
迪杰斯特拉(Dijkstra)算法主要是针对没有负值的有向图,求解其中的单一起点到其他顶点的最短路径算法。本文主要总结迪杰斯特拉(Dijkstra)算法的原理和算法流程,最后通过程序实现在一个带权值的有向图中,选定某一个起点,求解到达其它节点的最短路径,来加深对算法的理解。
1 算法原理
迪杰斯特拉(Dijkstra)算法是一个按照路径长度递增的次序产生的最短路径算法。下图为带权值的有向图,作为程序中的实验数据。

其中,带权值的有向图采用邻接矩阵graph来进行存储,在计算中就是采用n*n的二维数组来进行存储,v0-v5表示数组的索引编号0-5,二维数组的值表示节点之间的权值,若两个节点不能通行,比如,v0->v1不能通行,那么$graph[0,1]=\infty$ (采用计算机中最大正整数来进行表示)。那如何求解从v0每个v节点的最短路径长度呢?

首先,引进一个辅助数组cost,它的每个值$cost[i]$表示当前所找到的从起始点v0到终点vi的最短路径的权值(长度花费),该数组的初态为:若从v0到vi有弧,则$cost[i]$为弧上的权值,否则置$cost[i]$为$\infty$ 。显然,长度为:
$$
cost[j]=Min_i(graph[0,i] | v_i \in V)
$$
的路径就是从v0出发的长度最短的一条最短路径。此路径为$(v_0,v_j)$ ,那么下次长度次短的路径必定是弧$(v_0,v_i)$ 上的权值$cost[i](v_i \in V)$,或者是$cost[k](v_k \in S)$ 和弧$(v_k,v_i)$ 的权值之和。其中V:待求解最短路径的节点j集合;S:已求解最短路径的节点集合。
其实迪杰斯特拉(Dijkstra)最短路径算法是上一篇文迷宫问题求解之“A*搜索”(二)所讲到的 A*搜索算法中的一个特例,当A *搜索算法中 h(n)函数为0的时候,那么它就是迪杰斯特拉算法,算法原理一样,只不过在写程序的时候稍微有点区别而已。
2 算法流程
根据上面的算法原理分析,下面描述算法的实现流程。
初始化:初始化辅助数组cost,从v0出发到图上其余节点v的初始权值为:$cost[i]=graph[0,i] \ |\ v_i \in V$ ;初始化待求节点S集合,它的初始状态为空集。
选择节点$v_j$ ,使得$cost[j]=Min ( cost[i] | v_i \in V -S )$ ,$v_j$ 就是当前求的一条从v0出发的最短路径的终点,修改S集合,使得$S=S\bigcup V_j$ 。
修改从v0出发到节点V-S上任一顶点$v_k$ 可达的最短路径,若cost[j]+graph[j,k]<cost[k] ,则修改cost[k]为:cost[k]=cost[j]+graph[j,k] 。
重复操作2,3步骤,直到求解集合V中的所有节点为止。
其中最短路径的存储采用一个path整数数组,path[i]的值记录vi的前一个节点的索引,通过path一直追溯到起点,就可以找到从vi到起始节点的最短路径。比如起始节点索引为0,若path[3]=4, path[4]=0;那么节点v2的最短路径为,v0->v4->v3。
3 算法实现
采用c#语言对第2节中的算法流程进行实现,关键代码如下。
3.1 最短路径代码
class DijkstraSolution
{
/*
* 求解各节点最短路径,获取path,和cost数组,
* path[i]表示vi节点的前继节点索引,一直追溯到起点。
* cost[i]表示vi节点的花费
*/
public static void FindShortestPath(int[,] graph,int startIndex, int[] path, int[] cost,int max)
{
int nodeCount = graph.GetLength(0);
bool[] v = new bool[nodeCount];
//初始化 path,cost,V
for (int i = 0; i <nodeCount ; i++)
{
if (i == startIndex)//如果是出发点
{
v[i] = true;//
}
else
{
cost[i] = graph[startIndex,i ];
if (cost[i] < max) path[i] = startIndex;
else path[i] = -1;
v[i] = false;
}
}
//
for(int i=1;i<nodeCount;i++)//求解nodeCount-1个
{
int minCost = max ;
int curNode=-1;
for (int w = 0; w < nodeCount; w++)
{
if (!v[w])//未在V集合中
{
if(cost[w]<minCost)
{
minCost = cost[w];
curNode = w;
}
}
}//for 获取最小权值的节点
if (curNode == -1) break;//剩下都是不可通行的节点,跳出循环
v[curNode] = true;
for (int w = 0; w < nodeCount; w++)
{
if (!v[w] && (graph[curNode, w] + cost[curNode] < cost[w]))
{
cost[w] = graph[curNode, w] + cost[curNode];//更新权值
path[w] = curNode;//更新路径
}
}//for 更新其他节点的权值(距离)和路径
}//
}
}
3.2 调用代码
int max = 10000;
int[,] graph = new int[6, 6] {
{max,max,10,max,30,100},
{max,max,5,max,max,max},
{max,max,max,50,max,max},
{max,max,max,max,max,10},
{max,max,max,20,max,60},
{max,max,max,max,max,max},
};
int []path = new int[6];
int []cost = new int[6];
DijkstraSolution.FindShortestPath(graph, 0, path, cost,max);
3.3 运行结果

4 总结
迪杰特拉斯算法求解了一个起始节点到所有其他节点的最短路径,时间复杂度为$O(n^2)$ ,即使人们可能只想知道从起始节点到某个特定的节点的最短路径,时间复杂度同样为$O(n^2)$ 。
理解一个算法和实现一个算法还有有些区别的。理解一个算法,只需要明白算法原理和它的逻辑过程即可,但是实现一个算法,不仅要明白算法的逻辑过程,还考究我们的程序设计能力。
5 参考资料和资源
参考资料:严蔚敏的《数据结构c语言版》
源代码:http://download.csdn.net/download/mingge38/9657216
最短路径之迪杰斯特拉(Dijkstra)算法的更多相关文章
- JS实现最短路径之迪杰斯特拉(Dijkstra)算法
最短路径: 对于网图来说,最短路径是指两个顶点之间经过的边上权值和最少的路径,我们称第一个顶点是源点,最后一个顶点是终点 迪杰斯特拉 ( Dijkstra) 算法是并不是一下子就求出 了 Vo 到V8 ...
- [C++]单源最短路径:迪杰斯特拉(Dijkstra)算法(贪心算法)
1 Dijkstra算法 1.1 算法基本信息 解决问题/提出背景 单源最短路径(在带权有向图中,求从某顶点到其余各顶点的最短路径) 算法思想 贪心算法 按路径长度递增的次序,依次产生最短路径的算法 ...
- 最短路径算法-迪杰斯特拉(Dijkstra)算法在c#中的实现和生产应用
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思想),直到扩展到终点为止 贪心算法(Greedy ...
- 迪杰斯特拉Dijkstra算法介绍
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijk ...
- 最短路径-迪杰斯特拉(dijkstra)算法及优化详解
简介: dijkstra算法解决图论中源点到任意一点的最短路径. 算法思想: 算法特点: dijkstra算法解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树.该算法常用于路由算 ...
- 最短路径 - 迪杰斯特拉(Dijkstra)算法
对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd ...
- 图的最短路径---迪杰斯特拉(Dijkstra)算法浅析
什么是最短路径 在网图和非网图中,最短路径的含义是不一样的.对于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径. 对于网图,最短路径就是指两顶点之间经过的边上权值之和最 ...
- 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)
一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...
- 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(一)
一.算法介绍 迪杰斯特拉算法(英语:Dijkstra's algorithm)由荷兰计算机科学家艾兹赫尔·迪杰斯特拉在1956年提出.迪杰斯特拉算法使用了广度优先搜索解决赋权有向图的单源最短路径问题. ...
- C# 迪杰斯特拉(Dijkstra)算法
Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 其基本思想是,设置顶点集合S并不断地作 ...
随机推荐
- dock基本使用
通过Docker源安装最新版本通过Docker源安装最新版本 要安装最新的 Docker 版本,首先需要安装 apt-transport-https 支持,之后通过添加源来安装.要安装最新的 Dock ...
- Week3 博客阅读感想和代码复审
一.关于博客阅读感想 阅读了十多篇老程序员(大多在计算机相关行业工作超过10年)关于自身经历的博客,很有感触.这里一方面总结一下看博客的收获,另一方面写点自己的感受. 首先,这些博客不少涉及到了两大类 ...
- [操作系统实验lab3]实验报告
[感受] 这次操作系统实验感觉还是比较难的,除了因为助教老师笔误引发的2个错误外,还有一些关键性的理解的地方感觉还没有很到位,这些天一直在不断地消化.理解Lab3里的内容,到现在感觉比Lab2里面所蕴 ...
- IE11之F12 Developer Tools--概述篇
打开Developer Tools的方法: a. 点击F12 b. 在浏览器中选择Tools-->F12 Develooper Tools 打开后图示: 从上图我们可以看到,Developer ...
- 复利计算6.0—软件工程(web版本)
复利计算再升级------------------------------------------------------------ 客户在大家的引导下,有了更多的想法: 这个数据我经常会填.... ...
- Linq查询简介
查询是一种从数据源检索数据的表达式. 查询通常用专门的查询语言来表示. 随着时间的推移,人们已经为各种数据源开发了不同的语言:例如,用于关系数据库的 SQL 和用于 XML 的 XQuery. 因此, ...
- 【原创】本地通过IIS设置开发的localhost网站的域名改为个性域名方法
效果图: 操作步骤如下: 第一步: 在本地IIS上新建个网站,如下图所示 第二步,修改host文件 加配置节点如下图所示 第三步,在vs里面找到你的web项目, ...
- Dev 饼图
// 添加引用命名空间 using DevExpress.XtraCharts; /* *具体步骤:(1)先构建饼图对象的数据源DataTable * (2)再设置饼图对象的相关参数 * (3)饼图空 ...
- Netty学习之客户端创建
一.客户端开发时序图 图片来源:Netty权威指南(第2版) 二.Netty客户端开发步骤 使用Netty进行客户端开发主要有以下几个步骤: 1.用户线程创建Bootstrap Bootstrap b ...
- 关于 hangfire 的权限问题
hangfire 是一个分布式后台执行服务. 官网:http://hangfire.io/ 我看中hangfire的地方是 1:使用简单 2:多种持久化保存方案.支持sqlserver ,msmq等 ...