示例
问:求各地之间的最短路径长度及最短路径
答:
起点 | 终点 | 最短路径长度 | 最短路径 |
---|---|---|---|
A | B | 2 | A->B |
A | C | 4 | A->B->D->C |
A | D | 3 | A->B->D |
B | A | 1 | B->A |
B | C | 2 | B->D->C |
B | D | 1 | B->D |
C | A | 4 | C->B->A |
C | B | 3 | C->B |
C | D | 4 | C->B->D |
D | A | 5 | D->C->B->A |
D | B | 4 | D->C->B |
D | C | 1 | D->C |
算法思想
对于上述例子:
已知直接相连的顶点之间的路径(无中转顶点)
- 允许A作为中转顶点,求出各顶点之间的最短路径
- 允许A、B作为中转顶点,求出各顶点之间的最短路径
- 允许A、B、C作为中转顶点,求出各顶点之间的最短路径
- 允许A、B、C、D作为中转顶点,求出各顶点之间的最短路径
抽象之后:
若有n个顶点(V0、V1、…Vn-1),需要进行n步操作,每次向中转顶点中增加一个新的顶点
1、允许 V0 作为中转顶点,求出各顶点之间的最短路径
2、允许 V0、V1 作为中转顶点,求出各顶点之间的最短路径
……
n、允许 V0、V1、…Vn-1 作为中转顶点,求出各顶点之间的最短路径
算法过程
用到两个表记录数据:
- 路径长度表:记录两个顶点之间的最短路径长度
- 路径表:记录两个顶点之间的中转点
- -1:无中转点
- 0:中转点为A
- 1:中转点为B
- 2:中转点为C
- 3:中转点为D
初始状态的路径长度表如下:(和图的邻接矩阵一致)
初始状态的路径表如下:
第一步:允许A作为中转顶点
起点 | 终点 | 刚加入的中转顶点 | 原路径长度 | 新路径长度 | 是否修改 |
---|---|---|---|---|---|
A | B | A | 2 | 0+2=2 | ❌ |
A | C | A | 6 | 0+6=6 | ❌ |
A | D | A | ∞ | 0+∞=∞ | ❌ |
B | A | A | 1 | 1+0=1 | ❌ |
B | C | A | ∞ | 1+6=7 | ✅ |
B | D | A | 1 | 1+∞=∞ | ❌ |
C | A | A | ∞ | ∞+0=∞ | ❌ |
C | B | A | 3 | ∞+2=∞ | ❌ |
C | D | A | ∞ | ∞+∞=∞ | ❌ |
D | A | A | ∞ | ∞+0=∞ | ❌ |
D | B | A | ∞ | ∞+2=∞ | ❌ |
D | C | A | 1 | ∞+6=∞ | ❌ |
第二步:允许A、B作为中转顶点
起点 | 终点 | 刚加入的中转顶点 | 原路径长度 | 新路径长度 | 是否修改 |
---|---|---|---|---|---|
A | B | B | 2 | 2+0=2 | ❌ |
A | C | B | 6 | 2+7=9 | ❌ |
A | D | B | ∞ | 2+1=3 | ✅ |
B | A | B | 1 | 0+1=1 | ❌ |
B | C | B | 7 | 0+7=7 | ❌ |
B | D | B | 1 | 0+1=1 | ❌ |
C | A | B | ∞ | 3+1=4 | ✅ |
C | B | B | 3 | 3+0=3 | ❌ |
C | D | B | ∞ | 3+1=4 | ✅ |
D | A | B | ∞ | ∞+1=∞ | ❌ |
D | B | B | ∞ | ∞+0=∞ | ❌ |
D | C | B | 1 | ∞+7=∞ | ❌ |
第三步:允许A、B、C作为中转顶点
起点 | 终点 | 刚加入的中转顶点 | 原路径长度 | 新路径长度 | 是否修改 |
---|---|---|---|---|---|
A | B | C | 2 | 6+3=9 | ❌ |
A | C | C | 6 | 6+0=6 | ❌ |
A | D | C | 3 | 6+4=10 | ❌ |
B | A | C | 1 | 7+4=11 | ❌ |
B | C | C | 7 | 7+0=7 | ❌ |
B | D | C | 1 | 7+4=11 | ❌ |
C | A | C | 4 | 0+4=4 | ❌ |
C | B | C | 3 | 0+3=3 | ❌ |
C | D | C | 4 | 0+4=4 | ❌ |
D | A | C | ∞ | 1+4=5 | ✅ |
D | B | C | ∞ | 1+3=4 | ✅ |
D | C | C | 1 | 1+0=1 | ❌ |
第四步:允许A、B、C、D作为中转顶点
起点 | 终点 | 刚加入的中转顶点 | 原路径长度 | 新路径长度 | 是否修改 |
---|---|---|---|---|---|
A | B | D | 2 | 3+4=7 | ❌ |
A | C | D | 6 | 3+1=4 | ✅ |
A | D | D | 3 | 3+0=3 | ❌ |
B | A | D | 1 | 1+5=6 | ❌ |
B | C | D | 7 | 1+1=2 | ✅ |
B | D | D | 1 | 1+0=1 | ❌ |
C | A | D | 4 | 4+5=9 | ❌ |
C | B | D | 3 | 4+4=8 | ❌ |
C | D | D | 4 | 4+0=4 | ❌ |
D | A | D | 5 | 0+5=5 | ❌ |
D | B | D | 4 | 0+4=4 | ❌ |
D | C | D | 1 | 0+1=1 | ❌ |
至此,已求完所有的最短路径长度
接下来,根据 路径表 求最短路径,图中蓝色部分表示有中转顶点(值不为-1)
A至B、B至A、B至D、C至B、D至C直接就是最短路径,无中转点
A至C:
- 查A至C的数值为3,表明A与C之间有中转点为D
- 查A至D的数值为1,表明A与D之间有中转点为B
- 查A至B的数值为-1,表明A与B之间无中转点
- 查B至D的数值为-1,表明B与D之间无中转点
- 查D至C的数值为-1,表明D与C之间无中转点
- 查A至D的数值为1,表明A与D之间有中转点为B
所以最终得到A至C的最短路径为A->B->D->C
A至D:
- 查A至D的数值为1,表明A与D之间有中转点为B
- 查A至B的数值为-1,表明A与B之间无中转点
- 查B至D的数值为-1,表明B与D之间无中转点
所以最终得到A至D的最短路径为A->B->D
B至C:
- 查B至C的数值为3,表明B与C之间有中转点为D
- 查B至D的数值为-1,表明B与D之间无中转点
- 查D至C的数值为-1,表明D与C之间无中转点
所以最终得到B至C的最短路径为B->D->C
C至A:
- 查C至A的数值为1,表明C与A之间有中转点为B
- 查C至B的数值为-1,表明C与B之间无中转点
- 查B至A的数值为-1,表明B与A之间无中转点
所以最终得到C至A的最短路径为C->B->A
C至D:
- 查C至D的数值为1,表明C与D之间有中转点为B
- 查C至B的数值为-1,表明C与B之间无中转点
- 查B至D的数值为-1,表明B与D之间无中转点
所以最终得到C至D的最短路径为C->B->D
D至A:
- 查D至A的数值为2,表明D与A之间有中转点为C
- 查D至C的数值为-1,表明D与C之间无中转点
- 查C至A的数值为1,表明C与A之间有中转点B
- 查C至B的数值为-1,表明C与B之间无中转点
- 查B至A的数值为-1,表明B与A之间无中转点
所以最终得到D至A的最短路径为D->C->B->A
D至B:
- 查D至B的数值为2,表明D与B之间有中转点为C
- 查D至C的数值为-1,表明D与C之间无中转点
- 查C至B的数值为-1,表明C与B之间无中转点
所以最终得到D至B的最短路径为D->C->B