1、拓展边的操作一直执行到所有的dv都代表从s到v最短路径的花费。这个算法经过适当的组织因而当du达到它最终的值的时候,每条边(u,v)都只被拓展一次。算法维护两个顶点集S和Q。集合S保留了我们已知的所有dv的值已经是最短路径的值顶点,而集合Q则保留其他所有顶点。集合S初始状态为空,而后每一步都有一个顶点从Q移动到S。这个被选择的顶点是Q中拥有最小的du值的顶点。当一个顶点u从Q中转移到了S中,算法对每条外接边(u,v)进行拓展。算法思想设S为最短距离已确定的顶点集(看作红点集),V-S是最短距离尚未确定的顶点集(看作蓝点集)。初始化 初始化时,只有源点s的最短距离是已知的(SD(s)=0),故红
2、点集S=s,蓝点集为空。重复以下工作,按路径长度递增次序产生各顶点最短路径 在当前蓝点集中选择一个最短距离最小的蓝点来扩充红点集,以保证按路径权重递增的次序来产生各顶点的最短路径。 当蓝点集中仅剩下最短距离为的蓝点,或者所有蓝点已扩充到红点集时,s到所有顶点的最短路径就求出来了。 注意: 若从源点到蓝点的路径不存在,则可假设该蓝点的最短路径是一条长度为无穷大的虚拟路径。 从源点s到终点v的最短路径简称为v的最短路径;s到v的最短路径长度简称为v的最短距离,并记为SD(v)。(3)在蓝点集中选择一个最短距离最小的蓝点k来扩充红点集 根据按长度递增序产生最短路径的思想,当前最短距离最小的蓝点k的最
3、短路径是: 源点,红点1,红点2,红点n,蓝点k距离为:源点到红点n最短距离+边长 为求解方便,设置一个向量D0n-1,对于每个蓝点v V-S,用Dv记录从源点s到达v且除v外中间不经过任何蓝点(若有中间点,则必为红点)的最短路径长度(简称估计距离)。 若k是蓝点集中估计距离最小的顶点,则k的估计距离就是最短距离,即若Dk=minDi iV-S,则Dk=SD(k)。 初始时,每个蓝点v的Dc值应为权w,且从s到v的路径上没有中间点,因为该路径仅含一条边。 在蓝点集中选择一个最短距离最小的蓝点k来扩充红点集是Dijkstra算法的关键 (4)k扩充红点集s后,蓝点集估计距离的修改 将k扩充到红点
4、后,剩余蓝点集的估计距离可能由于增加了新红点k而减小,此时必须调整相应蓝点的估计距离。 对于任意的蓝点j,若k由蓝变红后使Dj变小,则必定是由于存在一条从s到j且包含新红点k的更短路径:P=且D j减小的新路径P只可能是由于路径和边组成。 所以,当length(P)=Dk+w小于Dj时,应该用P的长度来修改Dj的值。(5)Dijkstra算法Dijkstra(G,D,s) /用Dijkstra算法求有向网G的源点s到各顶点的最短路径长度 /以下是初始化操作 S=s;Ds=0; /设置初始的红点集及最短距离 for( all i V-S )do /对蓝点集中每个顶点i Di=Gsi; /设置i初
5、始的估计距离为w /以下是扩充红点集 for(i=0;iDk+Gkj) /新红点k使原Dj值变小时,用新路径的长度修改Dj, /使j离s更近。 Dj=Dk+Gkj; 已经利用优先队列实现了查找最短路径长度的dijkstra算法,怎么回溯出最短距离路线上经过的点呢?2011-5-25 20:47 提问者: 帝星卡卡22 | 浏览次数:291次/此程序成功找到了邻接矩阵中两点的最短距离长度,但是没有实现路径中经过的点的显示 #includequeuealgorithm using namespace std; #define INF 200 /最大距离表示节点之间不通 #define MAXN 1
6、100 struct way /放入优先队列Q中的结构体 int s;/v-s=d int d;/distance bool operator (const way k)const return k.dd;/sort from small to big ; int n; int mapMAXNMAXN; /存储邻接矩阵中节点间距离的数组 int pointMAXNMAXN;/pointij 存储节找到的点间最短距离的数组 void dijk(int v)/找到节点v到每个点的最短距离pointvi priority_queueQ; bool flagMAXN=false;/flagi=1 me
7、ans it is in the end point set way temp,now; now.s=v; /初始化way的实例now,并将节点加入队列 now.d=0; Q.push(now); pointvv=0; /初始化最短距离 /prevv=0; while(!Q.empty() now=Q.top(); /队列重排列 Q.pop();/使用优先队列的pop功能使已找到的最短距离节点出队列 if(flagnow.s) continue; flagnow.s=1; for(int i=1;=n;i+) if(!flagi&mapnow.si!=INF&pointvipointvnow.
8、s+mapnow.si) /修改经过now.s到集合任意点上可达的最短距离 temp.s=i; temp.d=pointvnow.s+mapnow.si; pointvi=temp.d; prevv=temp.s; Q.push(temp); void init()/初始化 int i,j; int a,b,c; prev = (int *)malloc(sizeof(int)*n); cout请输入邻接矩阵,权值间以空格分隔endl; for(i=1;i+) for(j=1;jj+) pointij=INF; /初始化最短路径 scanf(%d,&mapij);/输入邻接矩阵,200表示不通
9、 int main() int m;请输入节点个数 while(scanf(n)!=EOF&n!=0) /输入节点个数 init(); dijk(i);/find minimal distance between v to each point i int a,b;请输入起点a和终点b,以空格间隔%d%da,&b) if(a=0&b=0) break; else printf(%dn,pointab);/显示两点a b间最短路径距离#includeusing namespace std;#define INF 200 /最大距离表示节点之间不通#define MAXN 1100struct w
10、ay /放入优先队列Q中的结构体s=d/distance(const way k)const /sort from small to big ;int n;int mapMAXNMAXN;int pointMAXNMAXN;void dijk(int v)/找到节点v到每个点的最短距离pointvi/flagi=1 means it is in the end point setQ.empty()/使用优先队列的pop功能使已找到的最短距离节点出队列 if(flagnow.s)void init()/初始化i+)j+)/输入邻接矩阵,200表示不通int main()/find minimal
11、 distance between v to each point ib)b=0) else return 0;这个算法是通过为每个顶点v保留目前为止所找到的从s到v的最短路径来工作的。Dijstra算法的基础操作是边的拓展:初始化时,只有源点s的最短距离是已知的(SD(s)=0),故红点集S=s,蓝点集为空。在当前蓝点集中选择一个最短距离最小的蓝点来扩充红点集,以保证按路径权重递增的次序来产生各顶点的最短路径。当蓝点集中仅剩下最短距离为的蓝点,或者所有蓝点已扩充到红点集时,s到所有顶点的最短路径就求出来了。注意:若从源点到蓝点的路径不存在,则可假设该蓝点的最短路径是一条长度为无穷大的虚拟路径
12、。从源点s到终点v的最短路径简称为v的最短路径;根据按长度递增序产生最短路径的思想,当前最短距离最小的蓝点k的最短路径是:源点,红点1,红点2,红点n,蓝点k为求解方便,设置一个向量D0n-1,对于每个蓝点v V-S,用Dv记录从源点s到达v且除v外中间不经过任何蓝点(若有中间点,则必为红点)的若k是蓝点集中估计距离最小的顶点,则k的估计距离就是最短距离,即若Dk=minDi iV-S,则Dk=SD(k)。初始时,每个蓝点v的Dc值应为权w在蓝点集中选择一个最短距离最小的蓝点k来扩充红点集是Dijkstra算法的关键 将k扩充到红点后,剩余蓝点集的估计距离可能由于增加了新红点k而减小,此时必须调整相应蓝点的估计距离。对于任意的蓝点j,若k由蓝变红后使Dj变小,则必定是由于存在一条从s到j且包含新红点k的更短路径:所以,当length(P)=Dk+w/新红点k使原Dj值变小时,用新路径的长度修改Dj,/使j离s更近。Dj=Dk+Gkj;
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1