何谓最短路径
顾名思义就是在一个图中,一个顶点到另外一个顶点的最短距离拉。那么这里有一点要注意,就是在网图中(边的权值各不相同)最短路径指的是俩点之间的连线权值最小;在非网图(边的权值都默认为1)中最短路径指的是边数最少的。
从一个顶点到其余各顶点的最短路径
采用迪克斯特拉算法求解,基本思想是:
还是利用数组来找出最短路径,先循环遍历出第一个顶点A离其他顶点的距离,然后存储到一个数组里,这时候数组里对应的每一位就是各个顶点到A的距离。
找出距离最小的那个顶点B,重新计算B到其他顶点的距离,这里有一点要说明一下:比如顶点C,他到顶点A的路径可能经过B,又或者直接从A到C。这时候就需要A到B的距离加上B到C的距离之和与A到C的距离做比较,取出较小的那个存储到数组中。
那么这样说是简单,通过代码怎么实现呢?
//先进行初始化
//循环遍历出第一个顶点A离其他顶点的距离,然后存储到一个数组里,这时候数组里对应的每一位就是各个顶点到A的距离。
for(i=0;i<g.n;i++)
{
dist[i]=g.edges[v][i];
s[i] = 0; //s[i]标志着第i个顶点是否已经找到离某一点的最短路径
if(g.edges[v][i]<INF)
path[i] = g.edges[v][i];//path数组记录第i个顶点的上一个顶点位置
else
path[i] = -1;
}
关于s数组和path数组暂时不理解的可以看接下来的介绍。
接下来应该找出距离0顶点最近的那个点,就必须通过下面的代码:
min = INF;
//取出dist中最小的
for(j=0;j<g.n;j++)
{
if(s[j]==0 && dist[j]<min)
{
min = dist[j];
u = j;
}
}
s[u] = 1;
从上面的代码就可以找出距离顶点0权值最小的那个点了,从上面的思路中我们有提到dist数组存储的就是当前距离顶点0的权值最小的各条边。那么现在,我们要找出第三个顶点了,可以先看看下面的代码:
for(j=0;j<g.n;j++)
{ if(s[u]==0) if(g.edges[u][j]<INF && dist[u]+g.edges[u][j]<dist[j]) { dist[j] = dist[u]+g.edges[u][j]; path[j] = u; }
}
这一段代码完成的功能就是取出遍历跟第二个顶点相连的所有顶点,判断这些顶点与第一个顶点的距离会不会大于先连接第二个顶点再连接第一个顶点的距离,简单点说就是现在有三个村庄a,b,c。那么要做的就是判断c村直接到a村比较近,还是先过b村,再去a村比较近。所以这一段就是迪克斯特拉算法的精华之处
那么整个算法就是:
void Dijkstra(MGraph g,int v)
{
int dist[MAXV],path[MAXV];
int s[MAXV];
int i,j,min,u;
for(i=0;i<g.n;i++)
{
dist[i]=g.edges[v][i];
s[i] = 0;
if(g.edges[v][i]<INF)
path[i] = g.edges[v][i];
else
path[i] = -1;
}
for(i=0;i<g.n;i++)
{
min = INF;
//取出dist中最小的
for(j=0;j<g.n;j++)
{
if(s[j]==0 && dist[j]<min)
{
min = dist[j];
u = j;
}
}
//经过上面的遍历已经取出dist中最小的了,接下来要做的就是访问这个形成最小距离的顶点u
//设置已经访问
s[u] = 1;
for(j=0;j<g.n;j++)
{
if(s[u]==0)
if(g.edges[u][j]<INF && dist[u]+g.edges[u][j]<dist[j])
{
dist[j] = dist[u]+g.edges[u][j];
path[j] = u;
}
}
}
}