单源最短路径-Dijkstra算法
1.算法标签
贪心
2.算法描述
具体的算法描述网上有好多,我觉得莫过于直接wiki,只说明一些我之前比较迷惑的。
对于Dijkstra算法,最重要的是维护以下几个数据结构:
- 顶点集合S : 表示已经找出从源点出发最短路径的顶点集合
- 顶点集合Q: S在所有顶点集合中的补集,即V-S
- 距离数组dist : 在程序执行过程中,如果序号为n的顶点已经在S中,那么dist[n]表示从源点start到顶点n的最短距离,否则dist[n]的值将在程序执行过程中不断收敛。
- 路径数组previous: 当程序执行完成之后,previous[n]表示最短路径中顶点n的前一个顶点
程序执行时,每轮循环中,对Q中每个顶点u,计算源点经由S中顶点直接到达u的路径长度最小值,存入dist数组中,每轮循环只往S中加入一个顶点,这个顶点是Q中顶点dist值最小的那个,因此这是个贪心策略,为什么贪心策略是正确的?
- Dijskstra默认每条边都是正权值
- 因为S中的顶点的最短路径已经找到,所以加入的这个点肯定找不到一条更短的到源点的路径,否则说明S中的路径不是最短路径。
3.实现说明
实现时,Dijkstra算法可能会有多种改进,比如图用邻接表的形式存储,可以在稀疏图中获得更快的时间,然后计算dist最小值可以用最小堆来实现,这样就不必每次线性查找
4.一个例子(图片来源)
5.代码实现
//aouthor:areslipan
vector<int> Dijkstra(vector<vector<int> > &g, int vNum,int start)
{
vector<int>path(vNum,-1);//-1表示路径未找到
vector<int>dist(vNum,MYINF);
dist[start]=0;
set<int>source;//一旦一个点距离源点start最短路径被找到,那么该点就被加入集合source中
set<int>dest; //source 的补集
for(int i=0;i<vNum;++i)dest.insert(i); set<int>::iterator iter_s;
set<int>::iterator iter_d; int cur=start; while(!dest.empty())
{
int curMin=MYINF; //选出dest中dist最小的那个归入source中
for(iter_d=dest.begin();iter_d!=dest.end();++iter_d)
{
if(curMin>dist[*iter_d])
{
curMin=dist[*iter_d];cur=*iter_d;
}
} source.insert(cur);
dest.erase(cur); //加入一个新顶点之后开始更新dest中顶点的dist值,此处可以用最小堆优化
for(iter_s=source.begin();iter_s!=source.end();++iter_s)
{
for(iter_d=dest.begin();iter_d!=dest.end();++iter_d)
{
if((g[*iter_s][*iter_d]+dist[*iter_s])<dist[*iter_d])
{
dist[*iter_d]=g[*iter_s][*iter_d]+dist[*iter_s];
path[*iter_d]=*iter_s;
}
}
}
} return path;
}
上面这个程序算法时间复杂度较高,在优化实现的时候算法复杂度可以降低到O(NlgN),分析见wiki,这个程序只是作为说明的用途。
6.完整的程序文件
7.参考
参考1:http://www.wutianqi.com/?p=1890
参考2: wiki
参考3:文中链接
单源最短路径-Dijkstra算法的更多相关文章
- 单源最短路径Dijkstra算法,多源最短路径Floyd算法
1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...
- 单源最短路径——dijkstra算法
dijkstra算法与prim算法的区别 1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...
- 单源最短路径 dijkstra算法实现
本文记录一下dijkstra算法的实现,图用邻接矩阵表示,假设图为无向图.而且连通,有向图,不连通图的做法相似. 算法简述: 首先确定"单源"的源.假设是第0个顶点. 维护三个数组 ...
- 单源最短路径——Dijkstra算法学习
每次都以为自己理解了Dijkstra这个算法,但是过没多久又忘记了,这应该是第4.5次重温这个算法了. 这次是看的胡鹏的<地理信息系统>,看完之后突然意识到用数学公式表示算法流程是如此的好 ...
- [数据结构与算法-15]单源最短路径(Dijkstra+SPFA)
单源最短路径 问题描述 分别求出从起点到其他所有点的最短路径,这次主要介绍两种算法,Dijkstra和SPFA.若无负权优先Dijkstra算法,存在负权选择SPFA算法. Dijkstra算法 非负 ...
- matlab练习程序(单源最短路径Dijkstra)
图的相关算法也算是自己的一个软肋了,当年没选修图论也是一大遗憾. 图像处理中,也有使用图论算法作为基础的相关算法,比如图割,这个算法就需要求最大流.最小割.所以熟悉一下图论算法对于图像处理还是很有帮助 ...
- 单源最短路径---Bellman-Ford算法
传送门: Dijkstra Bellman-Ford SPFA Floyd 1.Dijkstra算法的局限性 像上图,如果用dijkstra算法的话就会出错,因为如果从1开始,第一步dist[2] = ...
- 洛谷P3371单源最短路径Dijkstra版(链式前向星处理)
首先讲解一下链式前向星是什么.简单的来说就是用一个数组(用结构体来表示多个量)来存一张图,每一条边的出结点的编号都指向这条边同一出结点的另一个编号(怎么这么的绕) 如下面的程序就是存链式前向星.(不用 ...
- 单源最短路径Dijkstra和优先级算法
百度百科:迪杰斯特拉算法. 代码实现如下: import java.util.Comparator; import java.util.PriorityQueue; import java.util. ...
随机推荐
- oracle数据库sql的基本使用
整理了下关于oracle数据库中SQL的基本使用语句,整理如下,方便记忆. oracle的基本术语 数据字典,数据库元数据信息的数据字典表和用户可以读取的数据字典视图组成.存放oracle数据库所用的 ...
- 深入理解Java内存模型(六)——final
与前面介绍的锁和volatile相比较,对final域的读和写更像是普通的变量访问.对于final域,编译器和处理器要遵守两个重排序规则: 在构造函数内对一个final域的写入,与随后把这个被构造对象 ...
- Ubuntu下eclipse的Extjs提示插件安装
使用eclipse编写extjs时,一定会用到spket这个插件,spket可以单独当作ide使用,也可以当作eclipse插件使用,我这里是当作eclipse的插件使用的,下面来一步步图解说明如何配 ...
- The GPG keys listed not correct
The GPG keys listed for the "Extra Packages for Enterprise Linux 5 - x86_64" repository ar ...
- Android构建boot.img(一):root目录与ramdisk.img的生成
以TCC88XX为例,当在Android顶层源码目录使用make编译完成后,会生成这样一个目录: out/target/product/tcc8800,该目录内部有我们需要的boot.img和syst ...
- cs108 java 02
Eclipise 1. import, 所有的homework 是以 eclipse project directories 的形式. 所以要选择 “File –> Import “, Exis ...
- codeforce Codeforces Round #201 (Div. 2)
cf 上的一道好题: 首先发现能生成所有数字-N 判断奇偶 就行了,但想不出来,如何生成所有数字,解题报告 说是 所有数字的中最大的那个数/所有数字的最小公倍数,好像有道理:纪念纪念: #incl ...
- Vagrant使用笔记
vagrant box add [options] <name, url, or path> - 添加box至vagrant的管理列表 vagrant init 初始化虚拟机至当前文件夹并 ...
- Task和BackTask
一.总结性知识点: 1.Android应用运行时会创建任务Task,用于存放主窗口 2.每一个任务包含一个堆栈数据结构,用于保存当前应用已创建的窗口对象,这个堆栈即回退栈BackSta ...
- UE删除空行
