最短路径.docx
- 文档编号:23191263
- 上传时间:2023-05-15
- 格式:DOCX
- 页数:14
- 大小:19.97KB
最短路径.docx
《最短路径.docx》由会员分享,可在线阅读,更多相关《最短路径.docx(14页珍藏版)》请在冰豆网上搜索。
最短路径
Dijkstra算法是由荷兰计算机科学家艾兹格·迪科斯彻发现的。
算法解决的是有向图中最短路径问题。
举例来说,如果图中的顶点表示城市,而边上的权重表示著城市间开车行经的距离。
Dijkstra算法可以用来找到两个城市之间的最短路径。
Dijkstra算法的输入包含了一个有权重的有向图G,以及G中的一个来源顶点S。
我们以V表示G中所有顶点的集合。
图中的每一个边,都是两个顶点所形成的有序元素对。
(u,v)表示从顶点u到v有路径相连。
假设E为所有边的集合,而边的权重则由权重函数w:
E→[0,∞]定义。
因此,w(u,v)就是从顶点u到顶点v的非负花费值(cost)。
边的花费可以想像成两个顶点之间的距离。
任两点间路径的花费值,就是该路径上所有边的花费值总和。
已知有V中有顶点s及t,Dijkstra算法可以找到s到t的最低花费路径(i.e.最短路径)。
这个算法也可以在一个图中,找到从一个顶点s到任何其他顶点的最短路径。
算法描述
这个算法是通过为每个顶点v保留目前为止所找到的从s到v的最短路径来工作的。
初始时,源点s的路径长度值被赋为0(d[s]=0),同时把所有其他顶点的路径长度设为无穷大,即表示我们不知道任何通向这些顶点的路径(对于V中所有顶点v除s外d[v]=∞)。
当算法结束时,d[v]中储存的便是从s到v的最短路径,或者是无穷大(如果路径不存在的话)。
Dijstra算法的基础操作是边的拓展:
如果存在一条从u到v的边,那么从s到v的最短路径可以通过将边(u,v)添加到s到u的尾部来拓展。
这条路径的长度是d[u]+w(u,v)。
如果这个值比目前已知的d[v]的值要小,我们可以用新值来替代当前d[v]中的值。
拓展边的操作一直执行到所有的d[v]都代表从s到v最短路径的花费。
这个算法经过适当的组织因而当d[u]达到它最终的值的时候,每条边(u,v)都只被拓展一次。
算法维护两个顶点集S和Q。
集合S保留了我们已知的所有d[v]的值已经是最短路径的值顶点,而集合Q则保留其他所有顶点。
集合S初始状态为空,而后每一步都有一个顶点从Q移动到S。
这个被选择的顶点是Q中拥有最小的d[u]值的顶点。
当一个顶点u从Q中转移到了S中,算法对每条外接边(u,v)进行拓展。
算法思想
设S为最短距离已确定的顶点集(看作红点集),V-S是最短距离尚未确定的顶点集(看作蓝点集)。
①初始化
初始化时,只有源点s的最短距离是已知的(SD(s)=0),故红点集S={s},蓝点集为空。
②重复以下工作,按路径长度递增次序产生各顶点最短路径
在当前蓝点集中选择一个最短距离最小的蓝点来扩充红点集,以保证按路径权重递增的次序来产生各顶点的最短路径。
当蓝点集中仅剩下最短距离为∞的蓝点,或者所有蓝点已扩充到红点集时,s到所有顶点的最短路径就求出来了。
注意:
①若从源点到蓝点的路径不存在,则可假设该蓝点的最短路径是一条长度为无穷大的虚拟路径。
②从源点s到终点v的最短路径简称为v的最短路径;s到v的最短路径长度简称为v的最短距离,并记为SD(v)。
(3)在蓝点集中选择一个最短距离最小的蓝点k来扩充红点集
根据按长度递增序产生最短路径的思想,当前最短距离最小的蓝点k的最短路径是:
源点,红点1,红点2,…,红点n,蓝点k
距离为:
源点到红点n最短距离+<红点n,蓝点k>边长
为求解方便,设置一个向量D[0..n-1],对于每个蓝点v∈V-S,用D[v]记录从源点s到达v且除v外中间不经过任何蓝点(若有中间点,则必为红点)的"最短"路径长度(简称估计距离)。
若k是蓝点集中估计距离最小的顶点,则k的估计距离就是最短距离,即若D[k]=min{D[i]i∈V-S},则D[k]=SD(k)。
初始时,每个蓝点v的D[c]值应为权w,且从s到v的路径上没有中间点,因为该路径仅含一条边。
注意:
在蓝点集中选择一个最短距离最小的蓝点k来扩充红点集是Dijkstra算法的关键
(4)k扩充红点集s后,蓝点集估计距离的修改
将k扩充到红点后,剩余蓝点集的估计距离可能由于增加了新红点k而减小,此时必须调整相应蓝点的估计距离。
对于任意的蓝点j,若k由蓝变红后使D[j]变小,则必定是由于存在一条从s到j且包含新红点k的更短路径:
P=。
且D[j]减小的新路径P只可能是由于路径和边
所以,当length(P)=D[k]+w
(5)Dijkstra算法
Dijkstra(G,D,s){
//用Dijkstra算法求有向网G的源点s到各顶点的最短路径长度
//以下是初始化操作
S={s};D[s]=0;//设置初始的红点集及最短距离
for(alli∈V-S)do//对蓝点集中每个顶点i
D[i]=G[s][i];//设置i初始的估计距离为w
//以下是扩充红点集
for(i=0;i D[k]=min{D[i]: alliV-S};//在当前蓝点集中选估计距离最小的顶点k if(D[k]等于∞) return;//蓝点集中所有蓝点的估计距离均为∞时, //表示这些顶点的最短路径不存在。 S=S∪{k};//将蓝点k涂红后扩充到红点集 for(allj∈V-S)do//调整剩余蓝点的估计距离 if(D[j]>D[k]+G[k][j]) //新红点k使原D[j]值变小时,用新路径的长度修改D[j], //使j离s更近。 D[j]=D[k]+G[k][j]; } } 数据结构——带权有向图(最短路径算法Dijkstra算法) 1.Dijkstra 1)适用条件&范围: a)单源最短路径(从源点s到其它所有顶点v); b)有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图) c)所有边权非负(任取(i,j)∈E都有Wij≥0); 2)算法描述: a)初始化: dis[v]=maxint(v∈V,v≠s);dis[s]=0;pre[s]=s;S={s}; b)Fori: =1ton 1.取V-S中的一顶点u使得dis[u]=min{dis[v]|v∈V-S} 2.S=S+{u} 3.ForV-S中每个顶点vdoRelax(u,v,Wu,v) c)算法结束: dis[i]为s到i的最短距离;pre[i]为i的前驱节点 3)算法优化: 使用二叉堆(BinaryHeap)来实现每步的DeleteMin(ExtractMin,即算法步骤b中第1步)操作,算法复杂度从O(V^2)降到O((V+E)㏒V)。 推荐对稀疏图使用。 使用FibonacciHeap(或其他Decrease操作O (1),DeleteMin操作O(logn)的数据结构)可以将复杂度降到O(E+V㏒V);如果边权值均为不大于C的正整数,则使用RadixHeap可以达到O(E+V㏒C)。 下面给出Java实现的源码: packagezieckey.datastructure.study.graph; /** * *带权重有方向图 *介绍了Dijkstra算法: 最短路径算法 * *Dijkstra算法原理: *1)适用条件&范围: a)单源最短路径(从源点s到其它所有顶点v); b)有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图) c)所有边权非负(任取(i,j)∈E都有Wij≥0); 2)算法描述: a)初始化: dis[v]=maxint(v∈V,v≠s);dis[s]=0;pre[s]=s;S={s}; b)Fori: =1ton 1.取V-S中的一顶点u使得dis[u]=min{dis[v]|v∈V-S} 2.S=S+{u} 3.ForV-S中每个顶点vdoRelax(u,v,Wu,v) c)算法结束: dis[i]为s到i的最短距离;pre[i]为i的前驱节点 3)算法优化: a)使用二叉堆(BinaryHeap)来实现每步的DeleteMin(ExtractMin,即算法步骤b中第1步)操作,算法复杂度从O(V^2)降到O((V+E)㏒V)。 推荐对稀疏图使用。 b)使用FibonacciHeap(或其他Decrease操作O (1),DeleteMin操作O(logn)的数据结构)可以将复杂度降到O(E+V㏒V);如果边权值均为不大于C的正整数,则使用RadixHeap可以达到O(E+V㏒C)。 * * *@authorzieckey * */ publicclassWeightedDirectedGraph { privatefinalintMAX_VERTS=20; privatefinalintINFINITY=1000000; privateVertex[]vertexList;//listofvertices privateint[][]adjMat;//adjacencymatrix privateintnVerts;//currentnumberofvertices privateintnTree;//numberofvertsintree privateDistanceParent[]shortestPath;//arrayforshortest-pathdata privateintcurrentVertex;//currentvertex privateintstartToCurrentDistance;//distancetocurrentVert publicWeightedDirectedGraph() { vertexList=newVertex[MAX_VERTS]; //adjacencymatrix adjMat=newint[MAX_VERTS][MAX_VERTS]; nVerts=0; nTree=0; for(intj=0;j { //setadjacency for(intk=0;k { adjMat[j][k]=INFINITY; } } shortestPath=newDistanceParent[MAX_VERTS];//shortestpaths } /** *求最短路径算法: Dijkstra算法。 */ publicvoidfindShortestPath() { intstartTree=0;//从0节点开始 vertexList[startTree].isInTree=true;//将该节点放入树中 nTree=1; //初始化最短路径表,以邻接矩阵中的startTree行数据初始化 for(inti=0;i { shortestPath[i]=newDistanceParent(startTree,adjMat[startTree][i]); } while(nTree { intindexMin=getMinFromShortestPath();//从最短路径表中得到目前的最小值 intminDist=shortestPath[indexMin].distance; if(minDist==INFINITY)//如果为INFINITY,表明不可达,或者都在树中了。 { System.out.println("Thereareunreachablevertices"); break;//sPathiscomplete }else { currentVertex=indexMin;//将最小的赋值给currentVert,为即将进入树中作准备 startToCurrentDistance=shortestPath[indexMin].distance;//路径权重最小 } //将当前节点放入树中 vertexList[currentVertex].isInTree=true; nTree++; adjust_sPath();//更新最短路径表 }//endwhile displayPaths();//displaysPath[]contents nTree=0;//cleartree for(intj=0;j { vertexList[j].isInTree=false; } } /** *显示最短路径 */ publicvoiddisplayPaths() { for(intj=0;j { System.out.print(vertexList[j].label+"=");//B= if(shortestPath[j].distance==INFINITY) { System.out.print("inf");//inf } else { System.out.print(shortestPath[j].distance);//50 } charparent=vertexList[shortestPath[j].parentVert].label; System.out.print("("+parent+")");//(A) } System.out.println(""); } /** *更新最短路径表 */ publicvoidadjust_sPath() { for(intcolumn=1;column { if(false==vertexList[column].isInTree)//如果不在树中 { //calculatedistanceforonesPathentry intcurrentToFringe=adjMat[currentVertex][column];//当前点到column的距离 intstartToFringe=startToCurrentDistance+currentToFringe;//计算起始点到column的距离 //与原来最短路径表中的权重值进行比较 if(startToFringe { shortestPath[column].parentVert=currentVertex; shortestPath[column].distance=startToFringe; }//endif }//endif }//endfor } /** *从最短路径表中得到目前的最小值 *@return返回最小值的index */ publicintgetMinFromShortestPath() { intminDist=INFINITY;//assumeminimum intindexMin=0; for(intj=1;j {//ifit'sintreeand if(! vertexList[j].isInTree&&//smallerthanoldone shortestPath[j].distance { minDist=shortestPath[j].distance; indexMin=j;//updateminimum } }//endfor returnindexMin; } /** *添加一条边 *@paramstart边的起点 *@paramend边的终点 *@paramweight边的权重 */ publicvoidaddEdge(intstart,intend,intweight) { adjMat[start][end]=weight;//有方向 } /** *添加一个节点 * *@paramlab */ publicvoidaddVertex(charlab)//argumentislabel { vertexList[nVerts++]=newVertex(lab); } } 其他类: packagezieckey.datastructure.study.graph; /** *在最短路径问题中,保存距离和到达该节点前最后一个必经节点 * *@authorzieckey */ publicclassDistanceParent { publicintdistance;//distancefromstarttothisvertex publicintparentVert;//currentparentofthisvertex publicDistanceParent(intpv,intd)//constructor { distance=d; parentVert=pv; } } === packagezieckey.datastructure.study.graph; /** * *图中的(节)点。 * *@authorzieckey * */ classVertex { publiccharlabel;//label(e.g.'A') publicbooleanwasVisited; publicbooleanisInTree; publicVertex(charlab)//constructor { label=lab; wasVisited=false; isInTree=false; } }//endclassVertex
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 路径