Dijkstra算法(单源最短路径)

来源:互联网 发布:mac ant安装 编辑:程序博客网 时间:2024/05/22 10:30

对于有向无环图DAG,我们可以利用先拓扑排序得到顶点的一个序列,然后按照此序列进行最短路径的推进(更新当前顶点的邻接顶点的dist值),如 图的邻接表数组实现及其应用

对于有环图,通常使用的是Dijkstra算法的技术,即每次选择在没被选择过(unknown,false)的顶点中当前dist 最小的顶点,然后将其置为已选择(如 visited[ i ] = true;),再进行最短路径的推进(更新当前顶点的邻接顶点的dist值,以供下次选择使用),这样就可以避免重复选择。

对于最短路径,最重要的就是已经选择过的顶点一定不能重复选择或参与以后的运算(dist值的更新),而上面两种策略就是解决这一问题的良药。


预备知识:

邻接矩阵:表示图的一种方法,是一个二维数组。用一个一维数组存放图中所有顶点数据;用一个二维数组存放顶点间关系(边)的数据,这个二维数组称为邻接矩阵。对于每条边(u , v),我们置A[u][v]=1;否则,置为0.如果边有一个权,我们可以置A[u][v]等于该权,而使用一个很大或者很小的权作为标记表示不存在的边。

注意,无向图的邻接矩阵一定是对称的,而有向图的邻接矩阵一般不对称。

单源最短路径问题,即在图中求出给定顶点到其它任一顶点的最短路径。在弄清楚如何求算单源最短路径问题之前,必须弄清楚最短路径的最优子结构性质。


1.最短路径的最优子结构性质

    该性质描述为:如果P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,k和s是这条路径上的一个中间顶点,那么P(k,s)必定是从k到s的最短路径。下面证明该性质的正确性。

    假设P(i,j)={Vi....Vk..Vs...Vj}是从顶点i到j的最短路径,则有P(i,j)=P(i,k)+P(k,s)+P(s,j)。而P(k,s)不是从k到s的最短距离,那么必定存在另一条从k到s的最短路径P'(k,s),那么P'(i,j)=P(i,k)+P'(k,s)+P(s,j)<P(i,j)。则与P(i,j)是从i到j的最短路径相矛盾。因此该性质得证。


2.Dijkstra算法描述

     由上述性质可知,如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点。那么(Vi...Vk)也必定是从i到k的最短路径。为了求出最短路径,Dijkstra就提出了以最短路径长度递增,逐次生成最短路径的算法。譬如对于源顶点V0,首先选择其直接相邻的顶点中长度最短的顶点Vi,那么当前已知可得从V0到达Vj顶点的最短距离dist[j]=min{dist[j],dist[i]+matrix[i][j]}。

根据这种思路,假设存在G=<V,E>,源顶点为V0,U={V0},dist[i]记录V0到i的最短距离,path[i]记录从V0到i路径上的i前面的一个顶点。
1.从V-U中选择使dist[i]值最小的顶点i,将i加入到U中;
2.更新与i直接相邻顶点的dist值。(dist[j]=min{dist[j],dist[i]+matrix[i][j]})
3.直到U=V,停止。


3.代码如下

void DijkstraPath(MGraph g,int *dist,int *path,int v0) //v0表示源顶点 {    int i,j,k;    bool *visited=(bool *)malloc(sizeof(bool)*g.n);    for(i=0;i<g.n;i++)      //初始化     {        if(g.matrix[v0][i]>0&&i!=v0)        {            dist[i]=g.matrix[v0][i];            path[i]=v0;     //path记录最短路径上从v0到i的前一个顶点         }        else        {            dist[i]=INT_MAX;    //若i不与v0直接相邻,则权值置为无穷大             path[i]=-1;        }        visited[i]=false;    }    path[v0]=v0;    dist[v0]=0;              //这一句很重要    for(i=0;i<g.n;i++) {         int min=INT_MAX; int u=v0; //为了第一次循环而必须赋值 for(j=0;j<g.n;j++) //寻找未被扩展的权值最小的顶点 {     if(visited[j]==false&&dist[j]<min) {        min=dist[j];    u=j; } }        visited[u]=true;        for(k=0;k<g.n;k++) //更新dist数组的值和路径的值         {             if(visited[k]==false&&g.matrix[u][k]>0&&min+g.matrix[u][k]<dist[k]) {    dist[k]=min+g.matrix[u][k];                            path[k]=u; } } } }


关于代码的解释和演示如下图所示:



原文地址:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html
                    http://www.cnblogs.com/dolphin0520/archive/2011/08/26/2155202.html

0 0
原创粉丝点击