Dijkstra算法——单源最短路径问题
学习一个点到其余各个顶点的最短路径——单源最短路径
Dijkstra算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法。是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。
迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
算法的基本思想:
每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径。
算法基本步骤如下:
1.将所有顶点分为两部分:已知最短路程的顶点集合P和未知最短路径的顶点集合Q。最开始,已知最短路径的顶点集合P中只有源点一个顶点。用一个book数组来记录哪些点 在集合P中。例如对于某个顶点i,如果book[i]为1则表示这个顶点在集合P中,如果book[i]为0则表示这个顶在集合Q中。
2.设置源点s到自己的最短路径为0即dis[s]=0。若存在有源点能直接到达的顶点i,则把dis[i]设为e[s][i]。同时把所有其他(源点不能直接到达)顶点的最短路径设为无穷。
3.在集合Q的所有顶点中选择一个离源点s最近的顶点u(即dis[u]最小)加入到集合P。并考察所有以点u为起点的边,对每一条边进行松弛操作。例如存在一条从u到v的边,那么可以通过将边u-->v添加到尾部来扩展一条从s到v的路径,这条路径的长度是dis[u]+e[u][v]。如果这个值比目前已知的dis[v]的值要小,我们可以用新值来替代当前dis[v]中的值。
4.重复第三步,如果集合Q为空,算法结束。最终dis数组中的值就是源点到所有顶点的最短路径。
应用:求下图中的1号顶点到2、3、4、5、6号顶点的最短路径
e |
1 |
2 |
3 |
4 |
5 |
6 |
1 |
0 |
1 |
12 |
-- |
-- |
-- |
2 |
-- |
0 |
9 |
3 |
-- |
-- |
3 |
-- |
-- |
0 |
-- |
5 |
-- |
4 |
-- |
-- |
4 |
0 |
13 |
15 |
5 |
-- |
-- |
-- |
-- |
0 |
4 |
6 |
-- |
-- |
-- |
-- |
-- |
-- |
这里用二维数组e来存储顶点之间边的关系,初始值如上图。
还需要一个一维数组dis来存储1号顶点到其余各顶点的初始路程。
第一步:初始化dis数组
第二步:找到了离1号最近的点2号,2号有两条边2->3和2->4。dis[2]+e[2][3]<dis[3],更新dis[3];dis[4]>dis[2]+e[2][4],更新dis[4]。
第三步:当前离1号最近的是4号,对4号的三条边4->3,4->5,4->6进行松弛,更新dis数组。
第四步:继续在3、5和6号中选择离1号最近的顶点,选择3号,对3号的所有出边3->5进行松弛,更新dis数组。
第五步:在剩下的5和6号中选择离1号最近的顶点,选择5号,对5号的所有出边5->6进行松弛,更新dis数组。
第六步:显然6号没有出边,所以dis数组中的所有值已经从“估计值”变成了“确定值”。
实现代码如下:
#include <stdio.h> int main()
{
int i, j, m, n;
int q1, q2, q3;
int u, v, min;
int e[][], dis[], book[];
int inf = ;//用inf表示我们认为的无穷值 scanf_s("%d %d", &n, &m);//读入n,m,n表示顶点个数,m表示边的条数
//初始化
for (i = ; i <= n; ++i)
{
for (j = ; j <= n; ++j)
{
if (i == j)
{
e[i][j] = ;
}
else
{
e[i][j] = inf;
}
}
} //读入边
for (i = ; i <= m; ++i)
{
scanf_s("%d %d %d", &q1, &q2, &q3);
e[q1][q2] = q3;//有向图
} //初始化dis数组,这里是1号顶点到其余各顶点的初始路程
for (i = ; i <= n; ++i)
{
dis[i] = e[][i];
} //book、数组初始化
for (i = ; i <= n; i++)
book[i] = ;
book[] = ;
// Dijkstra 算法核心
for (i = ; i < n; ++i) // 计算n-1次
{
//找到离1号顶点最近的顶点
min = inf;
for (j = ; j <= n; ++j)
{
if (dis[j] < min && book[j] == )
{
min = dis[j];
u = j; //u为最近的点
}
}
book[u] = ; //对u的所有出边进行“松弛”
for (v = ; v <= n; ++v)
{
if (e[u][v] != inf && dis[v] > dis[u] + e[u][v])
{
dis[v] = dis[u] + e[u][v]; //这个过程就是"松弛"
}
}
} printf("结果为:\n");
//输出最终的结果
for (i = ; i <= n; ++i)
{
printf(" 1号顶点到%d号顶点的最短距离为:%d\n",i, dis[i]);
}
printf("\n"); getchar();
getchar();
return ;
}
调试结果如下图:
Dijkstra算法——单源最短路径问题的更多相关文章
- Dijkstra求解单源最短路径
Dijkstra(迪杰斯特拉)单源最短路径算法 Dijkstra思想 Dijkstra是一种求单源最短路径的算法. Dijkstra仅仅适用于非负权图,但是时间复杂度十分优秀. Dijkstra算法主 ...
- Dijkstra算法——单源最短路算法
一.介绍 迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他各个节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先搜索思想),直到扩展到终点为止. 适用于有 ...
- hdu 2680 最短路径(dijkstra算法+多源最短路径单源化求最小值)这题有点意思
Choose the best route Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- 单源最短路径Dijkstra算法,多源最短路径Floyd算法
1.单源最短路径 (1)无权图的单源最短路径 /*无权单源最短路径*/ void UnWeighted(LGraph Graph, Vertex S) { std::queue<Vertex&g ...
- 单源最短路径——dijkstra算法
dijkstra算法与prim算法的区别 1.先说说prim算法的思想: 众所周知,prim算法是一个最小生成树算法,它运用的是贪心原理(在这里不再证明),设置两个点集合,一个集合为要求的生成树的 ...
- 【转】Dijkstra算法(单源最短路径)
原文:http://www.cnblogs.com/dolphin0520/archive/2011/08/26/2155202.html 单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路 ...
- 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)
一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...
- 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(一)
一.算法介绍 迪杰斯特拉算法(英语:Dijkstra's algorithm)由荷兰计算机科学家艾兹赫尔·迪杰斯特拉在1956年提出.迪杰斯特拉算法使用了广度优先搜索解决赋权有向图的单源最短路径问题. ...
- Dijkstra 单源最短路径算法
Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...
随机推荐
- fiddler 路由设置
REGEX:^http://data.51buy.com/biz/oppmsmobile/web/js/app/(.+)/(.+).js E:\svns\new\dev\webapp\data_ics ...
- Angular - - ngChange、ngChecked、ngClick、ngDblclick
ngChange 当用户更改输入时,执行给定的表达式.表达式是立即进行执行的,这个和javascript的onChange事件的只有在触发事件的变化结束的时候执行不同. 格式:ng-change=”v ...
- QT第二天学习
回顾: qmake: qmake -project //生成*.pro文件 qmake //makefile make 注:if(qmake -v >=5) then QT += widget ...
- jQuery基本过滤选择器
jQuery基本过滤选择器: <h1>this is h1</h1> <div id="p1"> <h2>this is h2< ...
- FP Tree算法原理总结
在Apriori算法原理总结中,我们对Apriori算法的原理做了总结.作为一个挖掘频繁项集的算法,Apriori算法需要多次扫描数据,I/O是很大的瓶颈.为了解决这个问题,FP Tree算法(也称F ...
- Android开发系列之屏幕密度和单位转换
由于Android的开源性,所以目前市面上面Android手机的分辨率特别多,这样的话就给我适配带来了一定的难度.要想做好适配,我们首先应该明白什么是分辨率.PPI.屏幕大小等概念,还有在不同的屏幕密 ...
- Spring之循环依赖
转:http://my.oschina.net/tryUcatchUfinallyU/blog/287936 概述 如何检测循环依赖 循环依赖如何解决 Spring如何解决循环依赖 主要的几个缓存 主 ...
- iOS 图片压缩方法
iOS 图片压缩方法 两种图片压缩方法 两种压缩图片的方法:压缩图片质量(Quality),压缩图片尺寸(Size). 压缩图片质量 NSData *data = UIImageJPEGReprese ...
- boneCP的连接管理
boneCP连接的实现 boneCP自己实现了标准的java.sql.Connection接口,除了会持有Connection对象之外,还会拥有一些属性用于标记连接的创建时间,空闲时间等. 比较重要的 ...
- 蓝桥网试题 java 基础练习 十六进制转十进制
---------------------------------------------------------------------------------------- 貌似用int类型不会超 ...