最短路径: Floyd+Dijkstra算法
1.问题
1 、用Floyd算法求解下图各个顶点的最短距离,给出距离矩阵。
2 、对于下图使用Dijkstra算法求由顶点a到顶点h的最短路径。
2.解析
Floyd算法
原理:首先假设a(i)(j)是节点i到节点j的最短距离假设,然后对于每一个节点k,我们判断a(i,k) + a(k,j) < a(i,j)是否成立,若成立,则a(i,j) = a(i,k) + a(k,j),说明从i到k再到j的路径比i直接到j的路径短。当我们遍历完所有节点k,a(i,j)中记录的便是i到j的最短路径的距离。
算法描述:1.从任意一条单边路径开始,所有两点之间的距离是边的权值,如果两点之间没有边相连,则权为无穷大inf.若是自身到自身,则为0
2.设i,j两点间的最短距离为e(i,j),选中一个节点k,若a(i,k) + a(k,j) < a(i,j),则更新a(i,j) = a(i,k) + a(k,j),n个节点更新n次后完成。
初始距离矩阵为:
Dijkstra算法:
原理:该算法基于贪心算法,首先指定一个源点S,然后声明一个数组dis来保存源点到各个顶点的最短距离和数组map来保存已经找到了最短路径的顶点。通过select和slack两个操作不断更新源点S到点V的距离,select即选择操作,每次找到距离源点S最近并未被map数组标记的点,然后将其标记。slack即松弛操作,遍历select得到的点V所有的边,若存在dis[k]>dis[v]+map[v][k],则更新最短路径为经过点v的路径。最后得到的dis数组就是最短距离,若数组为无穷大,则说明无法到达。
3.设计
Floyd核心算法:
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(e[i][j]>e[i][k]+e[k][j] )
e[i][j]=e[i][k]+e[k][j];
Dijkstra核心算法:
void Dijkstra(int v)
{
memset(vis,0,sizeof(vis));
for(int k=1;k<=n;k++)
{
dis[k]=map[v][k];
}
vis[v]=1;
for(int k=1;k<n;k++)
{
int min=Inf,temp;
for(int i=1;i<=n;i++)
{
if(!vis[i]&&dis[i]<min)
{
min=dis[i];
temp=i;
}
}
vis[temp]=1;
for(int i=1;i<=n;i++)
{
if(map[temp][i]+dis[temp]<dis[i])
{
dis[i]=map[temp][i]+dis[temp];
}
}
}
}
4.解析
Floyd算法:经过三层for循环,时间复杂度为O(n^3)
Dijkstra算法:对点集V进行选择操作,并对选择的点通过邻接矩阵进行相邻边的遍历操作,时间复杂度为O(n^2)