最短路径-迪杰斯特拉(dijkstra)算法及优化详解
简介:
dijkstra算法解决图论中源点到任意一点的最短路径。
算法思想:
算法特点:
dijkstra算法解决赋权有向图或者无向图的单源最短路径问题,算法最终得到一个最短路径树。该算法常用于路由算法或者作为其他图算法的一个子模块。
算法的思路
dijkstra算法采用的是一种贪心的策略,声明一个数组dis来保存源点到各个顶点的最短距离和一个保存已经找到了最短路径的顶点的集合:T,初始时,原点 s 的路径权重被赋为 0 (dis[s] = 0)。若对于顶点 s 存在能直接到达的边(s,m),则把dis[m]设为w(s, m),同时把所有其他(s不能直接到达的)顶点的路径长度设为无穷大。初始时,集合T只有顶点s。
然后,从dis数组选择最小值,则该值就是源点s到该值对应的顶点的最短路径,并且把该点加入到T中,OK,此时完成一个顶点,
然后,我们需要看看新加入的顶点是否可以到达其他顶点并且看看通过该顶点到达其他点的路径长度是否比源点直接到达短,如果是,那么就替换这些顶点在dis中的值。
然后,又从dis中找出最小值,重复上述动作,直到T中包含了图的所有顶点。
图解:
以上图G4为例,来对迪杰斯特拉进行算法演示(以第4个顶点D为起点)。以下B节点中23应为13。
初始状态:S是已计算出最短路径的顶点集合,U是未计算除最短路径的顶点的集合!
第1步:将顶点D加入到S中。
此时,S={D(0)}, U={A(∞),B(∞),C(3),E(4),F(∞),G(∞)}。 注:C(3)表示C到起点D的距离是3。
第2步:将顶点C加入到S中。
上一步操作之后,U中顶点C到起点D的距离最短;因此,将C加入到S中,同时更新U中顶点的距离。以顶点F为例,之前F到D的距离为∞;但是将C加入到S之后,F到D的距离为9=(F,C)+(C,D)。
此时,S={D(0),C(3)}, U={A(∞),B(23),E(4),F(9),G(∞)}。
第3步:将顶点E加入到S中。
上一步操作之后,U中顶点E到起点D的距离最短;因此,将E加入到S中,同时更新U中顶点的距离。还是以顶点F为例,之前F到D的距离为9;但是将E加入到S之后,F到D的距离为6=(F,E)+(E,D)。
此时,S={D(0),C(3),E(4)}, U={A(∞),B(23),F(6),G(12)}。
第4步:将顶点F加入到S中。
此时,S={D(0),C(3),E(4),F(6)}, U={A(22),B(13),G(12)}。
第5步:将顶点G加入到S中。
此时,S={D(0),C(3),E(4),F(6),G(12)}, U={A(22),B(13)}。
第6步:将顶点B加入到S中。
此时,S={D(0),C(3),E(4),F(6),G(12),B(13)}, U={A(22)}。
第7步:将顶点A加入到S中。
此时,S={D(0),C(3),E(4),F(6),G(12),B(13),A(22)}。
此时,起点D到各个顶点的最短距离就计算出来了:A(22) B(13) C(3) D(0) E(4) F(6) G(12)。
代码:
邻接矩阵:
#include<stdio.h> #include<string.h> #define inf 0x3f3f3f3f ][],dis[],visit[]; /* 关于三个数组:map数组存的为点边的信息,比如map[1][2]=3,表示1号点和2号点的距离为3 dis数组存的为起始点与每个点的最短距离,比如dis[3]=5,表示起始点与3号点最短距离为5 visit数组存的为0或者1,1表示已经走过这个点。 */ int n,m; int dijstra() { ,min,sum=; memset(visit,,sizeof(visit));//初始化为.,表示开始都没走过 ; i<=n; ++i) { dis[i]=map[][i]; } visit[]=; dis[]=; ; i<n; i++) { min=inf; ; j<=n; ++j) { &&min>dis[j]) { min=dis[j]; pos=j; } } visit[pos]=;//表示这个点已经走过 ; j<=n; ++j) { &&dis[j]>dis[pos]+map[pos][j])//更新dis的值 dis[j]=dis[pos]+map[pos][j]; } } return dis[n]; } int main() { int i,j; while(~scanf("%d%d",&n,&m),n||m)//n表示n个点,m表示m条边 { ; i<=n; ++i) { ; j<=n; ++j) { map[i][j]=inf;//开始时将每条边赋为最大值 } } int a,b,c; ; i<=m; ++i) { scanf("%d%d%d",&a,&b,&c); if(c<map[a][b])//防止有重边 map[a][b]=map[b][a]=c; } int count=dijstra(); printf("%d\n",count); } ; }
优先队列优化:
+; struct edge { int to,cost; }; typedef pair<int,int> P; //first 是最短距离,second 是顶点的编号 int V;//顶点个数 vector<edge> G[MAXV]; int d[MAXV]; /* 需要优化的是数值的插入(更新)和取出最小值两个操作,因此使用堆就可以了。 把每个顶点当前的最短距离用堆来维护,在更新最短距离时,把对应的元素往根的方向移动 以满足堆的性质。 而每次从堆中取出的最小值就是下一次要用的顶点。这样堆中的元素共有 O(V)个,更新和取 出的操作有 O(E)次,因此整个算法的复杂度是 O(ElogV)。 下面是使用 STL 的 priority_queue 实现。在每次更新时往堆里插入当前最短距离和顶点的 值对。 插入的次数是 O(E)次,当取出的最小值不是最短距离的话,就丢弃这个值。这样整个算法也 可以在同样的时间内完成。 */ void dijkstra(int s) { priority_queue<P,vector<P>,greater<P> > que; memset(d,INF,sizeof d); d[s] = ; que.push(P(,s)); //把起点推入队列 while(!que.empty()) { P p = que.top(); que.pop(); int v = p.second; //顶点的编号 if (d[v] < p.first) continue; ; i < G[v].size(); i++) { edge e = G[v][i]; if (d[e.to] > d[v] + e.cost) { d[e.to] = d[v] + e.cost; que.push(P(d[e.to],e.to)); } } } }
最短路径-迪杰斯特拉(dijkstra)算法及优化详解的更多相关文章
- 图的最短路径---迪杰斯特拉(Dijkstra)算法浅析
什么是最短路径 在网图和非网图中,最短路径的含义是不一样的.对于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径. 对于网图,最短路径就是指两顶点之间经过的边上权值之和最 ...
- 最短路径 - 迪杰斯特拉(Dijkstra)算法
对于网图来说,最短路径,是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点为源点,最后一个顶点为终点.最短路径的算法主要有迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd ...
- JS实现最短路径之迪杰斯特拉(Dijkstra)算法
最短路径: 对于网图来说,最短路径是指两个顶点之间经过的边上权值和最少的路径,我们称第一个顶点是源点,最后一个顶点是终点 迪杰斯特拉 ( Dijkstra) 算法是并不是一下子就求出 了 Vo 到V8 ...
- 最短路径算法-迪杰斯特拉(Dijkstra)算法在c#中的实现和生产应用
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思想),直到扩展到终点为止 贪心算法(Greedy ...
- 迪杰斯特拉Dijkstra算法介绍
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 基本思想 通过Dijk ...
- 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)
一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...
- 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(一)
一.算法介绍 迪杰斯特拉算法(英语:Dijkstra's algorithm)由荷兰计算机科学家艾兹赫尔·迪杰斯特拉在1956年提出.迪杰斯特拉算法使用了广度优先搜索解决赋权有向图的单源最短路径问题. ...
- C# 迪杰斯特拉(Dijkstra)算法
Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止. 其基本思想是,设置顶点集合S并不断地作 ...
- 迪杰斯特拉(Dijkstra)算法
# include <stdio.h> # define MAX_VERTEXES //最大顶点数 # define INFINITY ;//代表∞ typedef struct {/* ...
随机推荐
- java 面向对象编程(OOP)
java是一个支持并发.基于类和面向对象的计算机编程语言.下面列出了面向对象软件开发的优点: 代码开发模块化,更易维护和修改: 代码复用: 增加代码的可靠性和灵活性: 增加代码的可理解性. 封装 封装 ...
- You can't specify target table 'table' for update in FROM clause
delete from table1 where ID not in(select max(ID) ID from table1 group by row1) and row1 ) # 出现错误 # ...
- 希尔排序Shell sort
希尔排序Shell Sort是基于插入排序的一种改进,同样分成两部分, 第一部分,希尔排序介绍 第二部分,如何选取关键字,选取关键字是希尔排序的关键 第一块希尔排序介绍 准备待排数组[6 2 4 1 ...
- 单词转换成向量形式 word2vec
word2vec(word to vector)是一个将单词转换成向量形式的工具.可以把对文本内容的处理简化为向量空间中的向量运算,计算出向量空间上的相似度,来表示文本语义上的相 似度.word2ve ...
- 【BZOJ】1096 [ZJOI2007]仓库建设
[算法]DP+斜率优化 [题解]状态转移方程:f[i]=min(f[j]+g(i+1,j-1))+c[i] 关键在于如何O(1)计算g(i+1,j-1). 推导过程:http://blog.csdn. ...
- 对于所有对象都通用方法的解读(Effective Java 第三章)
这篇博文主要介绍覆盖Object中的方法要注意的事项以及Comparable.compareTo()方法. 一.谨慎覆盖equals()方法 其实平时很少要用到覆盖equals方法的情况,没有什么特殊 ...
- python碎片记录(一)
1.python中求幂运算 2**31-1 2的31次方减一(32位整型数据范围为-2^31~2^31-1,最高位为符号位,负向值比正向值绝对值大1) 2.python中整数除法 x=x//1 ...
- 寻找kernel32.dll的地址
为了寻找kernel32.dll的地址,可以直接输出,也可以通过TEB,PEB等查找. 寻找TEB: dt _TEB nt!_TEB +0x000 NtTib : _NT_TIB +0x01c Env ...
- fork与vfork区别
1. 地址空间各段拷贝: fork: 内核为子进程生成新的地址空间结构,拷贝父进程的代码段,数据空间,堆,栈到自身的地址空间,但注意:子进程的代码段并不会分配物理空间,而是指向父进程的代码段物理空间, ...
- 移动端测试===Android内存管理: 理解App的PSS
Android内存管理: 理解App的PSS 原文链接:http://www.littleeye.co/blog/2013/06/11/android-memory-management-unders ...