最端路径:对于网图来说,最短路径,是指两个顶点之间经过的边上权值之和最少的路径,并且称路径上的第一个顶点时源点,最后一个顶点是终点。算法主要有两种:迪杰斯特拉算法,弗洛伊德算法。
使用以上网图,分别对迪杰斯特拉算法和弗洛伊德算法进行说明。
迪杰斯特拉算法:
迪杰斯特拉算法采用了贪心的策略,可以求出顶点到图中每个点的最短路径,时间复杂度为:n^2。
申请shortesPath数组和fromVertex数组。
shortesPath数组存储从0顶点到其他顶点的最短距离。
fromVertex数组存储从0顶点到其他顶点经过了那些点。
(1)分别对shortesPath数组和fromVertex数组进行初始化(“#”不可达,红色表示该点被访问)。
0 | 1 | 2 | 3 | 4 | 5 | |
shortesPath | 0 | 9 | 4 | 24 | # | # |
fromVertex | 0 | 0 | 0 | 0 | 0 | 0 |
表达的含义为从0号点开始,经过0号点到达各个点(数据下表就表示各个点)的距离。(就是从0号点开始到各个点的距离)
(2)在shportPath数组中选择一个最小的点。因为4的值最小,所以选取的点为2号顶点。
(3)更新shortesPath数组的内容。计算比较从0直接到各个顶点的距离是否大于从0开始经过2号点再到达各个顶点的距离。和2直接相连的顶点有两个为3号顶点和5号顶点。因为24>4+e(2,3)=16,即从0号顶点直接到3顶点的权值(24)大于从0号顶点经过2号顶点到3号顶点的权值(16),将3号顶点的24修改为16。同理,#>4+e(2,5)=21,将5号顶点的#修改为21。并将fromVertex数组的3,5的内容修改为2。
更新后的表:
0 | 1 | 2 | 3 | 4 | 5 | |
shortesPath | 0 | 9 | 4 | 16 | # | 21 |
fromVertex | 0 | 0 | 0 | 2 | 0 | 2 |
再按照(2)的方法从shportPath数组(未被访问的点)中选择一个最小的点。因为9最小所以选择1号顶点。按照(3)的方法更新shortesPath数组的内容。
和1号顶点直接相连的顶点有3号顶点和4号顶点,又因为16>9+1=10,#>9+e(1,4)=11,
将3号顶点的值修改为10,4号顶点的值修改为11。将fromVertex数组的4的内容修改为1。
0 | 1 | 2 | 3 | 4 | 5 | |
shortesPath | 0 | 9 | 4 | 10 | 11 | 21 |
fromVertex | 0 | 0 | 0 | 1 | 1 | 2 |
重复(2)(3),直到所有点都被访问。
选取3号顶点,和3号顶点直接相连的顶点有0,1,2,4,5。
10+e(3,0)=10+24=34>0
10+e(3,1)=10+1=11>9
10+e(3,2)=10+12=22>4
10+e(3,4)=10+4=14>11
10+e(3,5)=10+4=14<21
0 | 1 | 2 | 3 | 4 | 5 | |
shortesPath | 0 | 9 | 4 | 10 | 11 | 14 |
fromVertex | 0 | 0 | 0 | 1 | ·1 | 3 |
选取4号顶点,和4号顶点直接相连的顶点1,3,5。
11+e(4,1)=11+2=13>9
11+e(4,3)=11+4=15>11
11+e(4,5)=11+9=20>14
0 | 1 | 2 | 3 | 4 | 5 | |
shortesPath | 0 | 9 | 4 | 10 | 11 | 14 |
fromVertex | 0 | 0 | 0 | 1 | 1 | 3 |
选取5号顶点,和5号顶点直接相连的顶点2,3,4。
14+e(5,2)=14+17=31>4
14+e(5,3)=14+4=18>10
14+e(5,4)=14+9=23>11
0 | 1 | 2 | 3 | 4 | 5 | |
shortesPath | 0 | 9 | 4 | 10 | 11 | 14 |
fromVertex | 0 | 0 | 0 | 1 | 1 | 3 |
所有顶点被访问,shortesPath数组中存储的就是从0号顶点开始到各个顶点的最短路径的权值。
结合fromVertex数组可以得出最短路径。
最短路径 | 权值 |
0--->1 | 9 |
0--->2 | 4 |
0---->1--->3 | 10 |
0---->1----->4 | 11 |
0----->1--->3---->5 | 14 |
//迪杰斯特拉算法
void Dijkstra(MGraph pGraph)
{
//记录最短路径的值的数组
int shortesPath[MAXVEX] ;
int visitVertex[MAXVEX];
//记录使用过顶点的集合
int fromVertex[MAXVEX];
for (int i= 0; i < pGraph.vertexNum; ++i)
{
shortesPath[i] = pGraph.graphEdge[0][i];
fromVertex[i] = 0;
visitVertex[i] = 0;
}
visitVertex[0] = 1;
for (int i = 1; i < pGraph.vertexNum; ++i)
{
int minWight = MINFINITE;
int min = -1;
for (int j = 1; j < pGraph.vertexNum; ++j)
{
if (visitVertex[j] == 0 && minWight>shortesPath[j])
{
minWight = shortesPath[j];
min = j;
}
}
visitVertex[min] = 1;
for (int j = 1; j < pGraph.vertexNum; ++j)
{
if (pGraph.graphEdge[min][j] != MINFINITE)
{
if (shortesPath[min] + pGraph.graphEdge[min][j] < shortesPath[j])
{
shortesPath[j] = shortesPath[min] + pGraph.graphEdge[min][j];
fromVertex[j] = min;
}
}
}
}
printf("最短路径权值:\n");
for (int i = 0; i < pGraph.vertexNum; ++i)
{
printf("%-3d,",shortesPath[i]);
}
printf("\n经过顶点:\n");
for (int i = 0; i < pGraph.vertexNum; ++i)
{
printf("%-3d,", fromVertex[i]);
}
printf("\n");
for (int i = 1; i < pGraph.vertexNum; ++i)
{
int j = i;
printf("%c--->",pGraph.graphVertex[i].data);
while (fromVertex[j] != 0)
{
printf("%c---->", pGraph.graphVertex[fromVertex[j]].data);
j = fromVertex[j];
}
printf("%c\n", pGraph.graphVertex[0].data);
}
}