最短路径之Dijkstra(迪杰斯特拉)算法(无向图)

简介


     Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。由for循环可知,其时间复杂度是O(n^2)。


原理


      在已知图的邻接矩阵net.vexs[i][j](无向网,含权值的图)的条件下,过遍历已知图的所有路径,用dis[i]数组来记录到i点的最短路径,然后在循环中不断判断更替。首先,将所有点的集合分为俩部分,一边是已经遍历过的,另外一边是没有遍历过的,分别用mark[i]=1、mark[i]=0来表示。


代码通解


             在下面代码中,先将赋予初始值dis[i]=INF(无穷大)、mark[i]=0(未标记),而后单独将源点(x)所联通的路径权值net.arcs[x][i]赋予dis[i](<INF称为初始化),i为联通的点,暂定为到i的最短路径,标记mark[x]=1,即已经遍历;然后,在一个for遍历了所有节点的大循环里面:

                                                          ①寻找遍历到点联通路径(与之相连线的点)中权值最小的一条; 标记遍历点;

                                                          ②修正最短路径;

而后,便是已经遍历所有点了,dis[i]也在不断的修正中得到真正的最小值,即最短路径。详情看下列代码


void Dijkstra(int x,int y)      // x为源点,y为终点
{
    int i,j,k;
    int min;
    int u;   //下一个放入集合p的点
    int dis[net.vexnum];   //  最短路径
    int mark[net.vexnum];   //   被mark的便是已经遍历,未被mark的便是未遍历
    /*首先进行最短路径初始化*/
    for(i=0; i<net.vexnum; i++)
    {
        mark[i] = 0;
        dis[i] = net.arcs[x][i];
    }


    mark[x]=1;          // 标记源点
    
    
    for(k=0; k<net.vexnum; k++)          // for 大循环
    {
        min = INF;   //  min初始化最大值,便于后来数据替换(每一个点的出度入度判断)
        
        /*寻找遍历到点联通路径(与之相连线的点)中权值最小的一条; 标记遍历点;*/
        for(i=0; i<net.vexnum; i++)
        {
            if(mark[i]==0&&min>dis[i])      //判断未遍历点 且 被赋值的最短路径(dis[i]<INF),未被赋值的点     //                                                     应当min==dis[i]=INF
            {
               min = dis[i];             //在已知赋值最短路径中,寻找权值最小的点并将他作为下一个遍历 
               u=i;                            //点u点
            }
        }


        mark[u]=1;      //标记u点
 
        /*修正最短路径*/
        for(i=0;i<net.vexnum;i++)
        {
            if(!mark[i]&&dis[i]>dis[u]+net.arcs[u][i])                 // !mark[i]判断不去走回头路,         //                                                                                dis[i]>dis[u]+net.arcs[u][i]有俩个用途:①若u链接的是x源点没有赋值最短路径的点,那么这里可以赋值②若是赋值过的点,那么可以判断是上一个dis[i](此时是被赋值过的)是不是真正的最短路径,即修正。

            {
                dis[i] = dis[u] + net.arcs[u][i];      //若A->C比A->B->C更长那么A->B->C则是到C的最短路径,下图将解释。
         
                   }
             }
    }
     printf("最短路径值为:             %d",dis[y]);
}

《最短路径之Dijkstra(迪杰斯特拉)算法(无向图)》我们以A,B,C三个点来举例子,三个点的最短路径分别为dis[0]、dis[1]、dis[2]。

                                                   ①A为源点初始化,dis[B]=3 (到B的最短路径,dis[1]),  dis[C]=6;

                                                   ②dis[B]<dis[C],选取B为u下一个遍历点;与B相联的有A(不走回头路)、E、C;

                                                   ③E未赋值,赋予dis[E];  C被之前赋予过,比较  dis[C] > dis[B] + net.arcs[B][C] (要不然你根本进不了这儿),重新赋值dis[C] = dis[B]+net.arcs[B][C];

                                                   ④大循环遍历所有点,走遍天下。



《最短路径之Dijkstra(迪杰斯特拉)算法(无向图)》

《最短路径之Dijkstra(迪杰斯特拉)算法(无向图)》

《最短路径之Dijkstra(迪杰斯特拉)算法(无向图)》



我觉得下面几张图很不错,图片取自https://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html

《最短路径之Dijkstra(迪杰斯特拉)算法(无向图)》

《最短路径之Dijkstra(迪杰斯特拉)算法(无向图)》



《最短路径之Dijkstra(迪杰斯特拉)算法(无向图)》




    原文作者:Dijkstra算法
    原文地址: https://blog.csdn.net/qq_37334150/article/details/79004785
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞