最短路径算法(Dijkstra)学习笔记
#include<iostream> #include<cstdlib> using namespace std; #define VEX 5//定义结点的个数 #define maxpoint 100 double graph[][maxpoint]= { { 0 , 10 , -1 , 30 , 100 }, { -1 , 0 , 50 , -1 , -1 } , { -1 , -1 , 0 , -1 , 10 } , { -1 , -1 , 20 , 0 , 60 } , { -1 , -1 , -1 , -1 , 0 } }; //邻接矩阵 int i,j; int main() { int R[maxpoint]= {0},B[maxpoint]; int D[VEX],P[VEX];//定义数组D用来存放结点特殊距离,P数组存放父亲结点 //初始时,红点集中仅有源结点0 R[0]=1; B[0]=0; for(int i=1; i<VEX; i++) B[i]=1; //对数组D、P进行初始化 for(i=0; i<VEX; i++) { D[i]=graph[0][i]; if(D[i]!=-1) P[i]=0; else P[i]=-1; } //输出邻接矩阵 for(i=0; i<VEX; i++) { for(int j=0; j<VEX; j++) cout<<graph[i][j]<<"\t"; cout<<endl; } //输出D、P表头 cout<<" "; for(i=0; i<VEX; i++) cout<<"D["<<i<<"] "; cout<<" "; for(i=0; i<VEX; i++) cout<<"P["<<i<<"] "; cout<<endl; for(int k=1; k<VEX; k++) //每次从蓝点集中取出具有最短特殊路长度的结点min { int MIN; for(MIN=0; B[MIN]==0;) MIN++; //求蓝点集结点最小下标元素 for(int j=MIN; j<VEX; j++) if(D[j]!=-1&&D[j]<D[MIN]&&B[j]==1) MIN=j; cout<<"MIN="<<MIN<<" "; //将具有最短特殊路长度的结点添加到红点集中 R[MIN]=1; B[MIN]=0; //对数组D作必要的修改 for(j=1; j<VEX; j++) if(graph[MIN][j]!=-1&&MIN!=j) //结点min到j间有路 if(D[j]>D[MIN]+graph[MIN][j]||D[j]==-1) { D[j]=D[MIN]+graph[MIN][j]; //每次迭代求最小值,最后一次即为到源点的最短路径 P[j]=MIN; } //输出最短路径 for(i=0; i<VEX; i++) cout<<D[i]<<" "; cout<<" "; for(i=0; i<VEX; i++) cout<<P[i]<<" "; cout<<endl; } }
Dijkstra算法
ØDijkstra算法是解单源最短路径问题的贪心算法。
Ø基本思想:设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。
(1)初始时,S中仅含有源节点。
(2)设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,用数组D[i]记录顶点i当前所对应的最短特殊路径长度。
(3)Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组D作必要的修改。
(4)一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。
Dijkstra算法的基本思想
Ø设S为最短距离已确定的顶点集(红点集)
ØV-S是最短距离尚未确定的顶点集(蓝点集)。
①初始化
最初只有源点s的最短距离是已知的(D(s)=0),故红点集S={s} 。
②重复以下工作,按路径长度递增次序产生各顶点最短路径
在当前蓝点集中选择一个最短距离最小的蓝点来扩充红点集,以保证算法按路径长度递增的次序产生各顶点的最短路径。
当蓝点集中仅剩下最短距离为∞的蓝点,或者所有蓝点已扩充到红点集时,s到所有顶点的最短路径就求出来了。
①初始化
最初只有源点s的最短距离是已知的(D(s)=0),故红点集S={s} 。
②重复以下工作,按路径长度递增次序产生各顶点最短路径
在当前蓝点集中选择一个最短距离最小的蓝点来扩充红点集,以保证算法按路径长度递增的次序产生各顶点的最短路径。
当蓝点集中仅剩下最短距离为∞的蓝点,或者所有蓝点已扩充到红点集时,s到所有顶点的最短路径就求出来了。
一个实例