1、Dijkstra算法:是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题。迪杰斯特拉算法主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。这个算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。注意该算法要求图中不存在负权边。
2、Dijkstra算法的思路:该算法主要是根据最短路径的不断更新,最后获得最短路径。在最开始确定起点和目的点,将起点的邻接点路径长设置为权重,将其他顶点设置为无穷大,依次访问邻接点,比较V+E(v,w)与Dist[w]的值,如果比他小,说明有更短的路径,就更新Dist[w]和path[w],不断地这样进行,知道所有的元素都被访问过后,就退出循环,得到最短路径。路径可以追溯path数组得到,思路流程图如图所示:
具体的通过例子进行理解。
3、Dijsktra算法的例子:
寻找最短路径的步骤:
(1)、确定起点V1,并初始化dist[1]=0,dist[2]=2,dist[4]=1,其他的初始化为正无穷,初始化后如图:
(2)、然后访问V2和V4其中路径短的那个,这里先访问V4,然后比较V4与邻接点之间的权重相加,如1+E(v4+v7)=5<正无穷,更新dist[7]=5和path[7]=4,同样的方法处理v5和v6。更新过后数组如图:
(3)、以此类推,继续访问知道所有的结点被标记访问退出。
代码实现:
Vertex FindMinDist( MGraph Graph, int dist[], int collected[] )
{ /* 返回未被收录顶点中dist最小者 */
Vertex MinV, V;
int MinDist = INFINITY;
for (V=0; V<Graph->Nv; V++) {
if ( collected[V]==false && dist[V]<MinDist) {
/* 若V未被收录,且dist[V]更小 */
MinDist = dist[V]; /* 更新最小距离 */
MinV = V; /* 更新对应顶点 */
}
}
if (MinDist < INFINITY) /* 若找到最小dist */
return MinV; /* 返回对应的顶点下标 */
else return ERROR; /* 若这样的顶点不存在,返回错误标记 */
}
bool Dijkstra( MGraph Graph, int dist[], int path[], Vertex S )
{
int collected[MaxVertexNum];
Vertex V, W;
/* 初始化:此处默认邻接矩阵中不存在的边用INFINITY表示 */
for ( V=0; V<Graph->Nv; V++ ) {
dist[V] = Graph->G[S][V];
if ( dist[V]<INFINITY )
path[V] = S;
else
path[V] = -1;
collected[V] = false;
}
/* 先将起点收入集合 */
dist[S] = 0;
collected[S] = true;
while (1) {
/* V = 未被收录顶点中dist最小者 */
V = FindMinDist( Graph, dist, collected );
if ( V==ERROR ) /* 若这样的V不存在 */
break; /* 算法结束 */
collected[V] = true; /* 收录V */
for( W=0; W<Graph->Nv; W++ ) /* 对图中的每个顶点W */
/* 若W是V的邻接点并且未被收录 */
if ( collected[W]==false && Graph->G[V][W]<INFINITY ) {
if ( Graph->G[V][W]<0 ) /* 若有负边 */
return false; /* 不能正确解决,返回错误标记 */
/* 若收录V使得dist[W]变小 */
if ( dist[V]+Graph->G[V][W] < dist[W] ) {
dist[W] = dist[V]+Graph->G[V][W]; /* 更新dist[W] */
path[W] = V; /* 更新S到W的路径 */
}
}
} /* while结束*/
return true; /* 算法执行完毕,返回正确标记 */
}