迪杰斯特拉算法
最短路径问题是指:从在带权图的某一顶点出发,找出一条通向另一顶点的最短路径。这里仅考虑,非负权值的单源路径最短
迪杰斯特拉算法,按路径的递增次序,逐步产生最短路径的算法。首先求出长度最短的一条最短路径,然后参照它求出长度次短的一条最短路径,依次类推,直到从顶点v到其他各顶点的最短路径全部求出为止。
迪杰斯特拉是位计算机大神,大师级人物.
该算法的思想:设定一个最短路径顶点集合,用于标记,每次找到当前最短路径,然后动态查找改变,下一个最短路径次序。
/*
Dijkstra算法:(i,j,k)
1、声明一个访问过结点集,用于标示每次是否被访问,初始化为假,对应已访问顶点集为空。
2、v=0;设置path数组,当此结点未访问,且小于最大值,设置路径为初始结点,
然后初始化当前最短路径数组dest,然后把初始结点设置为已访问过。
3、循环处理:
*/
void Dijkstra(int weight[5][5],int v,int dest[],int path[]) { int road[5]; int i,j ,k; bool shortset[5]; int min; //记录当前最小,选择一个结点和其他结点连接的最短路 int u; //用于记录是否经过u达到最短路径 int w; //辅助 for(i=0;i<5;i++) { dest[i]=weight[v][i]; shortset[i]=false; if(dest[i]<MaxValue) //如果有路,则将path数组设置为初始结点 path[i]=v; else path[i]=-1; } shortset[v]=true; dest[v]=0; for(i=0;i<4;i++) //循环处理到n-1个结点,里面的操作可以把最后一个结点加入到已访问集中 { min=MaxValue;u=v; //最新访问的 for(j=0;j<5;j++) if(shortset[j]==false&&dest[j]<min) { u=j; //j即为选出的最短路径结点 min=dest[j]; } //将此结点加入到最短路径集中 shortset[u]=true; for(k=0;k<5;k++) //动态测试模块:只修改路径,不访问结点 { w=weight[u][k]; //经过u到达其他结点 if(shortset[k]==false&&w<MaxValue&&dest[u]+w<dest[k]) { //缩短了路径,则把该结点加入到最短路径集中 dest[k]=dest[u]+w; // shortset[k]=true; //典型错误: path[k]=u; //类似并查集的索引 } } } //测试 cout<<"最短路径数组:"<<endl; for(i=0;i<5;i++) { cout<<dest[i]<<" "; } cout<<endl; cout<<"最短路径序列数组:"<<endl; for(i=0;i<5;i++) { cout<<path[i]<<" "; } cout<<endl; cout<<"访问控制数组:"<<endl; for(i=0;i<5;i++) { cout<<shortset[i]<<" "; } cout<<endl; //输出到各顶点的最短路径和最短路径序列 cout<<"-------测试结果---------------"<<endl; for(i=1;i<5;i++) { cout<<"顶点0到顶点"<<i<<"的最短路径长度为:"<<dest[i]<<endl; cout<<"最短路径序列为:"<<endl; //处理类似数组下标作为索引的数据结构的标准代码 k=0; int j=i; while(j>0) { // road[k++]=path[j--]; 有纰漏 road[k++]=j; j=path[j]; //顺次调用 } while(k>0) cout<<road[--k]<<" "; //k使用完还加1了,所以应该使用--k cout<<endl; cout<<endl; } }
主程序:
#define MaxValue 1999999 int _tmain(int argc, _TCHAR* argv[]) { int weight[5][5]= //用矩阵表示有向带权图 { {0,10,MaxValue,30,100}, {MaxValue,0,50,MaxValue,MaxValue}, {MaxValue,MaxValue,0,MaxValue,10}, {MaxValue,MaxValue,20,0,60}, {MaxValue,MaxValue,MaxValue,MaxValue,0} }; int dest[5]; //记录起始点到各个点的最短路径 int path[5]; //记录当该顶点经过的顶点次序 for(int i=0;i<5;i++) //都初始化为0 { dest[i]=0; path[i]=0; } //经验:典型,重点,难点,勿钻研生僻点 cout<<"------最短路径之Dijkstra算法------"<<endl; void Dijkstra(int weight[5][5],int v,int dest[],int path[]); //测试 Dijkstra(weight,0,dest,path); return 0; }
测试结果:
------最短路径之Dijkstra算法------
最短路径数组:
0 10 50 30 60
最短路径序列数组:
0 0 3 0 2
访问控制数组:
1 1 1 1 1
-------测试结果---------------
顶点0到顶点1的最短路径长度为:10
最短路径序列为:
1
顶点0到顶点2的最短路径长度为:50
最短路径序列为:
3 2
顶点0到顶点3的最短路径长度为:30
最短路径序列为:
3
顶点0到顶点4的最短路径长度为:60
最短路径序列为:
3 2 4
请按任意键继续. . .