在带权图(网)里,点A到点B所有路径中边的权值之和为最短的那一条路径,称为A,B两点之间的最短路径;并称路径上的第一个顶点为源点(Source),最后一个顶点为终点(Destination)。在无权图中,最短路径则是两点之间经历的边数最少的路径。实际上,只要把无权图上的每条边都看成是权值为1的边,那么无权图和带权图的最短路径是一致的。
   给定一个带权有向图G=(V,E),指定图G中的某一个顶点的V为源点,求出从V到其他各顶点之间的最短路径,这个问题称为单源点最短路径问题。
   迪杰斯特拉(Dijkstra)根据若按长度递增的次序生成从源点v0到其它顶点的最短路径,则当前正在生成的最短路径上除终点外,其余顶点的最短路径均已生成的这一思想,提出了按路径长度递增的次序产生最短路径的算法(在此,路径长度为路径上边和弧的权值之和)。Dijkstra算法的思想是:对带权有向图G=(V,E),设置两个顶点集合S和T=V-S;凡是以v0为源点并已确定了最短路径的终点(顶点)都并入到集合S,集合S的初态只含有源点v0;而未确定其最短路径的顶点均属于集合T,初态时集合T包含除了源点v0之外的其他顶点。按照各顶点与v0间最短路径的长度递增的次序,逐个把集合T中的各顶点的路径长度。并且,集合S中每加入一个新的顶点u,都要修改源点v0到集合T中剩余顶点的最短路径长度;也即,集合T中各顶点v新的最短路径长度值或是原来最短路径长度值,或是顶点u的最短路径长度值再加上顶点u到顶点v的路径长度值之和这两者中的较小值。这种把集合T中的顶点加入到集合S中的过程不断重复,直到集合T的顶点全部加入到集合S中为止。
   Dijkstra算法的实现中,以二维数组gm作为n个顶点带权有向图G=(V,E)的存储结构,并设置一个一维数组s(下标是0~n-1)用来标记集合S中已找到最短路径的顶点,而且规定:如果s[i]为0,则表示未找到源点v0到顶点vi的最短路径,也即此时vi在集合T中;如果s[i]为1,则表示已找到源点v0到顶点vi的最短路径(此时vi在集合S中).除了数组s外,还设置了一个数组dist(下标是0~n-1),用来保存从源点v0到终点vi的当前最短路径的长度.dist的初值为<v0,vi>边上的权值;若v0到vi没有边,则权值为&(无穷)。此后每当有一个新的顶点进入集合S中时,dist[i]值可能被修改变小.一维数组path(下标是0~n-1)用于保存最短路径长度中路径上边所经过的顶点序列;其中,path[i]保存从源点v0到终点vi当前最短路径中前一个顶点编号,它的初值是:如果v0到vi有边则置path[i]为v0的编号;如果v0到vi没有边则置path[i]为-1.
 参考代码:

 #include<stdio.h>
#define MAXSIZE 6
#define INF 32767 void Ppath(int path[],int i,int v0)//先序递归查找最短路径(源点为v0)上的顶点
{
int k;
k=path[i];
if(k!=v0)//顶点Vk不是源点V0时
{
Ppath(path,k,v0);//递归查找顶点Vk的前一个顶点
printf("%d,",k);//输出顶点Vk
}
} void Dispath(int dist[],int path[],int s[],int v0,int n)//输出最短路径
{
int i;
for(i=;i<n;i++)
if(s[i]==)//顶点Vi在集合S中
{
printf("从%d到%d的最短路径长度为:%d,路径为:",v0,i,dist[i]);
printf("%d,",v0);//输出路径上的源点v0;
Ppath(path,i,v0);//输出路径上的中间顶点vi
printf("%d\n",i);//输出路径上的终点
}
else
printf("从%d到%d不存在路径\n",v0,i);
} void Dijkstra(int gm[][MAXSIZE],int v0,int n)//Dijkstra算法
{
int dist[MAXSIZE],path[MAXSIZE],s[MAXSIZE];
int i,j,k,mindis;
for(i=;i<n;i++)
{
dist[i]=gm[v0][i];//v0到vi的最短路径初值赋给dist[i]
s[i]=;//s[i]=0表示顶点vi属于T集
if(gm[v0][i]<INF)//路径初始化,INF为可取的最大常数
path[i]=v0;
else
path[i]=-;//v0到vi没有边
}
s[v0]=;path[v0]=;//V0并入集合S且V0当前最短路径中无前一个顶点
for(i=;i<n;i++)//对除V0外的n-1个顶点寻找最短路径,即循环n-1次
{
mindis=INF;
for(j=;j<n;j++)//从当前集合T中选择一个路径长度最短的顶点Vk
if(s[j]==&&dist[j]<mindis)
{
k=j;
mindis=dist[j];
}
s[k]=;//顶点Vk加入集合S中
for(j=;j<n;j++)//调整源点v0到集合T中任一顶点Vj的路径长度
if(s[j]==)//顶点vj在集合T中
if(gm[k][j]<INF&&dist[k]+gm[k][j]<dist[j])//当V0到Vj的路径长度小于V0到Vk和Vk到Vj的路径长度时
{
dist[j]=dist[k]+gm[k][j];
path[j]=k;//Vk是当前最短路径中Vj的前一个顶点
}
}
Dispath(dist,path,s,v0,n);//输出最短路径
} void main()
{
int g[MAXSIZE][MAXSIZE]={{INF,,,INF,INF,INF},{,INF,INF,INF,,},{INF,,INF,INF,INF,},
{INF,INF,INF,INF,INF,INF},{INF,INF,INF,,INF,INF},{INF,INF,INF,,,INF}};//定义邻接矩阵g
Dijkstra(g,,);//求顶点0的最短路径
}

输出:

带权有向图及邻接矩阵示意:

最新文章

  1. Python第一天 - set
  2. tshark 抓包分析
  3. C++线程池
  4. 在忘记root密码的情况下如何修改linux系统的root密码
  5. Python [Leetcode 350]Intersection of Two Arrays II
  6. 04_过滤器Filter_03_多个Filter的执行顺序
  7. poj 1696 Space Ant(模拟+叉积)
  8. js获取时间天数
  9. 关于QuartusII对ram块的综合
  10. [转]A Faster UIWebView Communication Mechanism
  11. 关于Two-Pass标记连通域个数
  12. hdu 5584 gcd/lcm/数学公式
  13. [Hadoop] - TaskTracker源码分析(TaskTracker节点健康状况监控)
  14. 用Socket编写的聊天小程序
  15. IDEA 安装配置可视化 MongDB 插件
  16. Learning-Python【32】:进程理论基础
  17. 解析LED发光效率
  18. 如何让classmethod只允许使用用类对象来调用
  19. JAVA jar 参数
  20. PHP中curl模拟post上传及接收文件

热门文章

  1. 自定义函数,根据p个数,自适应剧中效果
  2. Spring Filter过滤器,Spring拦截未登录用户权限限制
  3. ZooKeeper观察者(十三)
  4. 51Nod 1001数组中和等于K的数对
  5. 转【es中数据节点和主机】
  6. 原生js实现单屏滚动
  7. [BZOJ2946][Poi2000]公共串解题报告|后缀自动机
  8. js 重置表单
  9. js 作用域链&amp;内存回收&amp;变量&amp;闭包
  10. Python的异常处理机制 -- (转)