dijkstra求最短路径长度
来源:互联网 发布:wine for mac下载 编辑:程序博客网 时间:2024/05/21 10:48
概述
dijkstra算法是单源最短路径算法的一种。
所谓单源,即在一个有向图中,从一个节点出发,算法可求该节点至所有可到达节点的最短路径长度。与之相对的称为非单源最短路,即算法运行一次可求出任意节点至任意可到达节点的最短路长度,其代表是floyd算法。单源最短路有两种常见算法,dijkstra算法和bellman-ford算法。前者只能用于求路径权值全部为非负数的最短路,但后者是可以求边权中出现负数的算法。既然非单源一次可以求出任意节点间的最短路,我们为什么还要使用单源算法呢?
因为floyd的时间复杂度为O(n^3),而dijkstra只有O(n^2)。如果要求出任意节点间的最短路,那么两个算法似乎都是O(n^3),然而floyd似乎更好理解。
dijkstra算法描述:
设G=(V,E)是一个有向图,V表示顶点,E表示边;它的每一条边(i,j)属于E,都有一个非负权W(i,j);在G中指定一个结点V0,要求求出从V0到G的每一个节点Vj(Vj属于V)的最短路径长度。
举例
根据下图,求从节点0开始到各节点的最短距离:
配合图中右边的过程:
- 首先我们先将从节点0出发的所有路径长度标记为无穷大。
- 由于从节点0出发,故更新从节点0到其直接相邻节点的路径长度,0->1:10,0->3:30,0->4:100。
- 取出其中最小的0->1:10,并且我们已经清楚0->1的距离已经是最短的了。
解释:从0到1无非两种走法,0直接到达1或0通过其他节点到达1。现在0到1的距离为10,其已小于0到其余节点的距离,即0->C->1=(30或100)+C->1,0->C->1已经不可能小于现在的0->1了,故现在的0->1已经是最短的,不可能有更短的0->1。
接着我们看下从节点1到其余节点的路径,明显有一条1->2:50,通过1->2可以产生0->1->2:60这条路径,该路径长度远小于现在表里的0->2为无穷大,故更新0->2:60。 - 接下来取出表里最小且没有使用过的值,0->3:30。同理,从节点3到节点2、4有直接的路径,得出0->3->2:50,其小于表中的0->2:60,故更新;0->3->4:90,其小于表中的0->4:100,故更新。
- 到此时,0->1:10,0->2:50,0->3:30,0->4:90,其中节点0、1、3已经被使用过,所以下面我们取出表里的最小且没有使用过的值,0->2:50。同理,节点2到4有一条直接路径,0->2->4:100,但其大于表中的0->4:90,故不更新。
算法步骤
步骤一:初始路径长度均为无穷大,将出发节点作为节点B和A。
步骤二:找到A节点射出的路径,将A节点作为中途节点,C为任意节点。当B->A->C<B->C,更新表中B->C的长度。
步骤三:从表中选出最小且未作为过A节点的值,将其对应的节点作为A;重复步骤二,直至所有节点均被作为过A节点。
代码实现
根据上图的例子,给出对应的算法,求解从节点0到各节点的最短路长度:
#include<stdio.h>const int N=100;const int INF=100000; //INF假定为无穷大int p[N][N],d[N]; //p表示各节点间的距离,不存在路径即为无穷大;d表示从出发节点到各节点的最短路径长度void dijkstra(int sec,int n) //sec为出发节点,n为图中的节点数{ int i,j,min,min_num; int vis[N]={0,}; //用于标记是否已作为过中途节点,0表示没有,1表示有 for(i=0;i<n;i++) //初始化 { d[i]=p[sec][i]; } vis[sec]=1;d[sec]=0; //出发节点到自己的距离永远为0 for(i=1;i<n;i++) { min=INF; for(j=0;j<n;j++) //每次循环取出d数组中的未被作为过中途节点且数值最小的 { if(!vis[j]&&d[j]<min) { min=d[j]; //更新最小值 min_num=j; //更新最小值所对应的节点,即记录下标 } } vis[min_num]=1; //标记该节点,表示其已被作为中途节点 for(j=0;j<n;j++) //循环,经过min_num节点到达是否有更小距离,如有更小距离则更新d数组 { if(d[j]>min+p[min_num][j]) { d[j]=min+p[min_num][j]; } } }}int main(){ int i,j,n=5; //n表示图中的节点个数 for(i=0;i<n;i++) //程序用二维数组p存储各节点间的距离,这里则进行初始化 { for(j=0;j<n;j++) { p[i][j]=(i==j?0:INF); //初始化:i到j路径为无穷大或者i到i本身为0 } } p[0][1]=10;p[0][3]=30;p[0][4]=100;p[1][2]=50;p[2][4]=50;p[3][2]=20;p[3][4]=60; //p[i][j]表示节点i到节点j的距离 dijkstra(0,n); //求从节点0出发到各节点的最短距离 for(i=0;i<n;i++) //打印从节点0出发到各节点的最短距离 { printf(i==n-1?"%d\n":"%d ",d[i]); } return 0;}
记录路径
如何在求最短路长度的同时记录路径呢?可以看这篇博客“dijkstra求最短路并记录路径”
0 0
- dijkstra求最短路径长度
- 单源最短路径长度Dijkstra(迪杰斯特拉)算法
- Dijkstra求最短路径
- 求最短路径(dijkstra)
- dijkstra 求最短路径算法
- dijkstra 求最短路径
- Dijkstra算法求最短路径
- Dijkstra 算法求最短路径
- 解析dijkstra求最短路径
- Dijkstra算法求最短路径
- Dijkstra算法求最短路径
- Dijkstra 求最短路径算法
- Dijkstra求最短路径
- dijkstra求最短路径(水题)
- Dijkstra算法 ---求最短路径
- Dijkstra求最短路径
- Dijkstra算法求最短路径
- dijkstra算法求最短路径
- CSS checkbox
- POJ 2155 二维线段树【线段树套线段树】
- object与byte[]的相互转换、文件与byte数组相互转换
- Android概述
- [转]如何在Ubuntu 14.04中安装最新版Eclipse
- dijkstra求最短路径长度
- Win10 多用户远程登录成功实然无法远程的问题
- [floyd]poj1125 Stockbroker Grapevine
- Hibernate的java.lang.StackOverFlowError问题
- 51nod 矩阵取数问题
- 考上北大有什么用?
- 在csdn中搜索自己的文章
- UVALive 6859 (凸包)
- android app 框架之BaseActivity