最短路径Dijkstra算法分析
生长点 | A | B | C | D | E |
F | P(A)=FA D(A)=130 | P(B)=FB D(B)=24 | P(C)=FC D(C)=10 | P(D)=—— D(D)=无穷 | P(E)=—— D(E)=无穷 |
C | P(A)=FA D(A)=130 | P(B)=FB D(B)=24 | P(D)=FCD D(D)=16 | P(E)=FCE D(E)=62 | |
D | P(A)=FA D(A)=130 | P(B)=FB D(B)=24 | P(E)=FCE D(E)=62 | ||
B | P(A)=FBA D(A)=80 | P(E)=FBE D(E)=50 | |||
E | P(A)=FBEA D(A)=60 | ||||
A |
* 图的存储方式为邻接表*
符号解释:
P(A):以当前生长点到A的最短路径
D(A):P(A)路径长度的权值和
过程解释:
1.以F为生长源点,与F的邻接点有A,B,C。
2.其中FC的路径长度最短,以C为新的生长点。
C的临接点有B,D,E:
(1)F直接到B的路径长度为24,F经过C到B的路径长度为27,直接到B的路径长度短,不作路径更新。同理,
(2)F到D的路径长度更新为10+6=16。
(3)F到E的路径长度更新为10+52=62。
3.其中FCD的路径长度最短,以D为新的生长点。
D的邻接点有F,显然成环回到起点,不做更新。
4.其中FB的路径长度最短,以B为新生长点,B的邻接点有A,E:
(1)从F经B到A的路径长度为24+56=80,显然小于直接从F到A的路径长度。故做更新。
(2)FBE路径长度为24+26=50<62(FCE)。故做更新。
5.其中FBE的路径最短,以E为新生长点,E的邻接点为A。
FBEA的路径长度为24+26+10=60<80(FBA)。故做更新。
至此,所有非源点的最短路径找到,过程结束。
简易代码描述:
void shortpath_dijkstra(L[M], int n, int s) // L[M],n顶点数,s源点号
{
// 设置待定路径初值
for (int i = 0; i < n; i++)
{
L[i].path = L[s].name; // 初始化路径为源点
L[i].dist = MAX; // 初始化距离为最大值
L[i].mark = 0; // 初始化标记为未访问
}
// 设置 s 为源点
L[s].mark = 1;
L[s].dist = 0;
// 更新源点的直接邻接边的距离
ArcNode *p = L[s].firstarc;
while (p != NULL)
{
int w = p->adjvex;
L[w].dist = p->cost;
L[w].path = L[s].name + L[w].name; // 更新路径
p = p->next;
}
for (int i = 0; i < n - 1; i++) // n - 1次
{
int k = -1;
int d = MAX;
// 找到未标记的最近顶点
for (int j = 0; j < n; j++)
{
if (L[j].mark == 0 && L[j].dist < d) // 修正索引
{
k = j;
d = L[j].dist;
}
}
if (k == -1) break; // 如果没有找到可访问的节点,提前退出。
L[k].mark = 1; // 标记为已访问
// 更新与 k 相连的未标记顶点的距离和路径
p = L[k].firstarc;
while (p != NULL)
{
int w = p->adjvex;
if (L[w].mark == 0 && L[w].dist > L[k].dist + p->cost)
{
L[w].path = L[k].path + L[w].name; // 更新路径
L[w].dist = L[k].dist + p->cost; // 更新距离
}
p = p->next;
}
}
}
代码分析
-
初始化:
- 代码开始时对每个顶点的
path
、dist
和mark
进行了初始化。 path
存储了从源点到该顶点的路径,dist
存储了源点到该顶点的距离,mark
用于标记该顶点是否已被访问。
- 代码开始时对每个顶点的
-
设置源点:
- 将源点的
mark
设置为 1,表示已访问,并将其dist
设置为 0。
- 将源点的
-
更新邻接顶点的距离:
- 使用
p
遍历源点的所有邻接边,更新相邻顶点的距离。
- 使用
-
主循环:
- 在主循环中,找到未被访问的顶点中距离最小的一个顶点
k
,并将其标记为已访问。 - 然后,更新从
k
到其邻接顶点的最短路径。
- 在主循环中,找到未被访问的顶点中距离最小的一个顶点
本文参考陈卫卫老师课程。