1.问题
定义G为任意超过两个顶点的有向连通图,若点i到j存在路径,则一定存在一条i到j的最短路径。本次实验将运用Floyd和Dijkstra求解最短路问题。
2.解析
Floyd算法:
1.选取1作为中间点,遍历整图,mp[4][1]+mp[1][3]<mp[4][3],所以mp[4][3]更新为11,见图1
图1
2.选取2作为中间点,遍历整图,mp[1][2]+mp[2][3]<mp[1][3],所以mp[4][3]更新为5,见图2
图2
3.选取3作为中间点,遍历整图,无需更新,见图3
图3
4.选取4作为中间点,遍历整图,mp[3][4]+mp[4][1]<mp[3][1],所以mp[3][1]更新为6,见图4
图4
Dijkstra算法
设dis[i]为起点到i的最短路径值,初始值为inf;vis[i]为点是否被访问过,初始值为false
1.以a作为起点,遍历寻找dis最小的点b,并标记,再更新其他点的dis值
id a b c d e f g h
dis 0 1 inf 3 inf inf inf inf
vis true true false false flase flase flase flase
2.遍历所有未被访问的点,选取dis最小的点d,标记并更新dis值
id a b c d e f g h
dis 0 1 4 3 inf 11 inf inf
vis true true false true flase flase flase flase
3.遍历所有未被访问的点,选取dis最小的点c,标记并更新dis值
在这里插入图片描述
id a b c d e f g h
dis 0 1 4 3 inf 11 inf inf
vis true true true true flase flase flase flase
4.遍历所有未被访问的点,选取dis最小的点f,标记并更新dis值
id a b c d e f g h
dis 0 1 4 3 13 11 inf inf
vis true true true true flase true flase flase
5.遍历所有未被访问的点,选取dis最小的点e,标记并更新dis值
id a b c d e f g h
dis 0 1 4 3 13 11 15 inf
vis true true true true true true flase flase
6.遍历所有未被访问的点,选取dis最小的点g,标记并更新dis值
id a b c d e f g h
dis 0 1 4 3 13 11 15 18
vis true true true true true true true flase
7.遍历所有未被访问的点,选取dis最小的点h,标记并更新dis值
id a b c d e f g h
dis 0 1 4 3 13 11 15 18
vis true true true true true true true true
8.得出答案,a到h的最短路径值为18
3.设计
void Floyd()
{
for (k遍历点集)
for (i遍历点集)
for (j遍历点集)
if (mp[i][k] + mp[k][j] < mp[i][j])
mp[i][j] = mp[i][k] + mp[k][j];
}
void Dijkstra(int s, int t)
{
memset(vis, false, sizeof(vis));
dis[s] = 0;
vis[s] = true;
for (遍历n-1次)
{
p=未被标记且dis最小的点
for (遍历点集)
if (!vis[j] && dis[j] > dis[p] + mp[p][j])
更新dis[j]的值
}
cout << dis[t] << endl;
}
4.分析
Floyd存储图的数据结构是二维数组,所以空间复杂度为S(n^2)
时间复杂度有三重循环,每一次都遍历点集,所以时间复杂度为O(n^3)
Djikstra存储图的数据结构是二维数组,所以空间复杂度为S(n^2)
算法中有两重循环,最外层为循环n-1次,内循环有两个,其中一个是选取未被标记且dis最小的点,另外一个则是以选取点来更新dis,都循环n次,所以时间复杂度为O(n^2)