数据结构23————图的最短路径Dijkstra算法&Floyd算法
一. 目录
文章目录
二. 最短路径的概念
从某顶点(源点)出发到另一顶点(目的点)的路径中,有一条各边(或弧)权值之和最小的路径称为最短路径。
形式化表述:
设有带权的有向图D=(V,{E}),D中的边权为W(e)。已知源点为v0,求v0到其它各顶点的最短路径。
最短路径有两种算法:迪杰斯特拉(Dijkstra)算法和弗洛伊德(Floyd)算法
三. 迪杰斯特拉算法
1. 定义概览
Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。
问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径。(单源最短路径)
2. 算法思想
如果源点v0到顶点vi的弧是v0到各点(最短)路径集合中最短者,则一定可以确定的是< v0,vi>是源点v0到vi的最短路径。
-
第一条最短路径(vo到vi是所有点中路径最短)最短路径的特点:
这条路径上,必定只含有一条弧,并且这条弧权值最小。 -
下一条(路径次短)的最短路径的特点:
它只含有两种情况:或者直接从源点到改点vj,或者从源点到vi,在到达vj -
再下一条长度次短的特点:
它可能有两种情况:或者直接从源点到达改点,或者从源点到达vi/cj,然后到达该点 -
其余最短路径的的特点:
它或者是直接从源点到该点(只含一条弧); 或者是从源点经过已求得最短路径的顶点,再到达该点
3. 算法步骤
- 初始化:S={v},v为源点。U={除V外所有点}
- 从U中选择到v距离最小的顶点k,把K加入到S中。
- 把k作为新的中间点,更新U中各点到源点的距离
- 重复2,3过程直到所有点都在S中
4. 动画演示
5. 代码实现
//G-->图,v0-->源点,P[v]表示v前驱顶点下标,D[v]表示V0到v的最短路径长度和
void ShortestPath_Dijkstra(AdjMatrix *G,int v0,int *P,int *D){
int v,w,k,min;
int book[MAXVEX]; //标记顶点v是否已找到最短路径
for(v=0;v<G->vexnum;v++){ //初始化数据
book[v]=0;
P[v]=0;
D[v]=G->acre[0][v];
}
D[v0]=0; //v0到v0距离为0
book[v0]=1;
//开始主循环,每次求得v0到某个顶点的最短距离
for(v=1;v<G->vexnum;v++){
min=INFINITY;
for(w=0;w<G->vexnum;w++){ //寻找到达v0距离最短的点
if(!book[w]&&D[w]<min){
k=w;
min=D[w];
}
}
book[k]=1; //将此时找到的点标记
for(w=0;w<G->vexnum;w++){ //根据本次找达v0最短的点,更新其他点到v0的距离
//如果经过顶点k的路径比现在路径更短的话
if(!book[w]&&(min+G->acre[k][w]<D[w])){
D[w]=min+G->acre[k][w];
P[w]=k;
}
}
}
}
四. 弗洛伊德算法
1. 定义概览
Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。Floyd-Warshall算法的时间复杂度为O(N3),空间复杂度为O(N2)。
2. 算法思想
从vi到vj的所有可能存在的路径中,选出一条长度最短的路径。
3. 算法过程
定义N阶方阵序列: D − 1 , D 0 , D 1 , D 2 . . . . D n − 1 D^{-1},D^0,D^1,D^2 .... D^{n-1} D−1,D0,D1,D2....Dn−1
D − 1 [ i ] [ j ] = G . a r c [ i ] [ j ] D^{-1}[i][j] = G.arc[i][j] D−1[i][j]=G.arc[i][j]
$ D^k[i][j] = Min{ D{k-1}[i][j],D{k-1}[i][K]+D^{k-1}[k][j] }$
显然:
D
k
[
i
]
[
j
]
D^k[i][j]
Dk[i][j]是从vi到vj的所经顶点的序号不大于k的最短路径长度。
D
n
D^n
Dn中为所有顶点偶对vi、vj间的最终最短路径长度。
4. 画片演示
矩阵坐标从0开始
5.代码实现
//G-->图,v0-->源点,P[v][w]表示v到其余各点w最短路径,D[v][w]表示v到其余各点w的带权路径长度和
void ShortestPath_Floyd(AdjMatrix *G,int P[MAXVEX][MAXVEX],int D[MAXVEX][MAXVEX]){
int v,w,k;
//初始化D和P
for(v=0;v<G->vexnum;v++){
for(w=0;w<G->vexnum;w++){
D[v][w] = G->acre[v][w];
P[v][w] = w;
}
}
for(k=0;k<G->vexnum;k++){
for(v=0;v<G->vexnum;v++){
for(w=0;w<G->vexnum;w++){
if(D[v][w]>D[v][k]+D[k][w]){ //如果经过下标为k的顶点路径比原两点间的路径更短,则更新
D[v][w] = D[v][k]+ D[k][w];
P[v][w] = P[v][k]; //路径设置经过下标为k的顶点
}
}
}
}
}
解读路径矩阵P:
已0到3为例:
p[0][3]=1,所以0–>1;
p[1][3]=3,所以1–>3;
所以0到3:0–>1–>3
五. 源码地址
六. 参考资料
《大话数据结构》
《数据结构与算法》