轻松掌握Dijkstra算法(最短路径算法)


void ShortestPath_DIJ(MGraph G, int v0, PathMatrix &P, ShortPathTable &D)
{
    /**
     * 核心原理:
     * 记已求得的最短路径终点的集合为S,假设要加入的终点是x顶点,那么下一条最短路径要么是
     * 直接弧(v0,x),要么就是中间经过S中顶点而最后到达终点x的路径(v0,...,x)。
     * 证明:(反证法)
     * 假设下一条最短路径中经过一个顶点不在S中,那么说明存在一条终点不在S而长度比此路径短的路径。
     * 但是这是不可能的,因为算法是按路径长度递增的次序来产生各路径的,故长度比此路径短的所有路径
     * 均已产生,它们的终点必定在S中,即假设不成立。(理解:如果有一条最短路径中经过一个顶点不在
     * S中,由于这个不在S中的顶点到终点x的弧权值大于0,所以从起始点v0到这个顶点的最短路径比起始
     * 点v0到终点x的最短路径肯定要短,那么这一次选取的终点就不应该是x了,与假设矛盾。)
     */
   
    /**
     * 定义说明:
     * 用Dijkstra算法求v0点到其它各个顶点的最短路径问题。
     * G表示用二维表数组表示的图信息,其中(v,w)表示顶点v到顶点w的边权值。
     * v0表示图G中的起始点。
     * D是一个记录起始点v0到各个顶点的最短路径长度的一维数组。
     * 若P[v][w]为TRUE,则表示从v0顶点到v顶点的最短路径经过w顶点。
     * 若final[v]为TRUE,则表示v顶点已经被包含在最短路径集合中。
     */
   
    /**
     * 处理过程:
     * 1. 初始化操作(最短路径顶点集合S、最短路径矩阵P、最短路径数组D)
     * 2. 主循环操作
     *      2.1 根据最短路径数组D来挑选一个顶点加入到已处理的集合S中(最短路径顶点集合S)
     *      2.2 最新当前最短路径数组D和最短路径矩阵P(最短路径矩阵P、最短路径数组D)
     */
   
    int v = 0;
    int w = 0;
    int i = 0;
    int j = 0;
    int min = INF;                          /** INF表示无穷大 */
    int* final = new int[G.vexnum];         /** 表示最短路径顶点集合S */

                                            /** 初始化操作(最短路径顶点集合S、最短路径矩阵P、最短路径数组D) */
    for(v = 0; v < G.vexnum; v++)
    {
        final[v] = FALSE;                   /** 初始化最短路径顶点集合S */
        D[v] = G.arcs[0][v];                /** 初始化最短路径数组D */
        for(w = 0; w < G.vexnum; w++)
        {
            P[v][w] = FALSE;                /** 初始化最短路径矩阵P */
        }
        if(D[v] < INF)
        {
                                            /** 第一次以起始点v0来记录最短路径矩阵P */
            P[v][v0] = TRUE;
            P[v][v] = TRUE;
        }
    }
    final[v0] = TRUE;                       /** 第一次以起始点v0加入到最短路径顶点集合S */
    D[0] = 0;                               /** 第一次以起始点v0记录初始化最短路径数组D */
   
                                            /** 主循环操作 */
    for(i = 1; i < G.vexnum; i++)
    {
                                            /** 根据最短路径数组D来挑选一个顶点加入到已处理的集合S中 */
        min = INF;
        for(w = 0; w < G.vexnum; w++)
        {
            if(!final[w] && min > D[w])
            {
                min = D[w];
                v = w;
            }
        }
        final[v] = TRUE;                    /** 更新最短路径顶点集合S(将新顶点加入集合S中) */
        for(w = 0; w < G.vexnum; w++)
        {
            if(!final[w] && min + G.arcs[v][w] < D[w])
            {
                D[w] = min + G.arcs[v][w];  /** 更新最短路径数组D(保持D数组是最小的路径值) */
                                            /** 更新最短路径矩阵P(记录到P[w][w]最短路径经过自身,且照搬前面顶点v的路径过程) */
                P[w][w] = TRUE;
                for(j = 0; j < G.vexnum; j++)
                {
                    P[w][j] = P[v][j];
                }
            }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值