Dijkstra 算法-《数据结构》严蔚敏

  1. 应用介绍
    假定某个销售做年度出差计划,每次需要从固定城市出发,去其它城市推销产品,那么问题就来了,如果求得从固定城市到其它拜访城市的最短路径或最小时间呢? 这就是一个典型的Dijkstra求解问题。
  2. Dijkstra算法介绍
    假定需要求出从某个单源点至其它节点的最短距离或最小路程,我们需要抽象两个结合,S集合和(V-S)集合。S集合中的点表示其所有最小距离已经求出,并且按照路径长度递增的次序来产生路径,(V-S)集合表示,待定求最短距离的顶点。
    求解过程中,我们需要借助三个数组保存记录:
    P[v][w] 数组,表示w属于从源点v0至v上最小距离的点,
    D[v]数组,表示从v0至v的当前的最短距离值
    final[v]数组,标明点V是否在集合S中

我们把程序分为几段来进行阐述:
2.1 初始化操作
借助双重循环,完成P[v][w]的初始化,如果过程中顶点v从v0可以到达,那么需要对P[v][w]数组的值进行更新。过程中标记final[v]为未访问,同时利用邻接表求出D[v]的值。

2.2 从V-S集合中进行贪心搜索
依次遍历除源点之外的G.vexnum-1个顶点,最外层循环主要控制对顶点遍历数量的控制。在每次循环中,需要从(V-S)集合中搜索某个最小的D[v],并保留v值。完成后,需要把v归并到S集合中。

2.3 由于v归并到S集合中
那么就会对(V-S)中的D[v]值进行再评估,有些教材上称之为relaxation. 由于v顶点的加入,那么就有两种情况,对于(V-S)中顶点的D[w]值,可能存在的情况之一,把v加入路径上之后,能有效降低D[v]的权值。这种情况下就需要采用循环进行D[w]数值的更新。
在此过程中,严蔚敏的数据结构中出现了令人不解的伪代码,伪代码如下:
Dijkstra 算法-《数据结构》严蔚敏_第1张图片
很多人对P[w]=P[v]百思不得其解,其实思路很简单,这里需要赋值第v行的值至第w行当中去。同时困惑大家的还有P[w][w]表达式,它表示把上述行复制完成后,把顶点w加入到v0到顶点w(同一个w)的数组中去。P[w]=P[v]可以采用memcpy赋值完成,p[w][w]就是一个简单的赋值操作。

  1. 算法的实现
    图的储存采用严蔚敏数据结构中的邻接矩阵,方便进行D[v]赋值操作,如果采用邻接表,需要进行判断后赋值。
int final[MAX_VERTEX_NUM];

typedef int PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef int ShortPathTable[MAX_VERTEX_NUM];

void ShortestPath_Dijkstra(MGraph G, int v0, PathMatrix P, ShortPathTable D)
{
    int min;
    int i;
    int v;
    int w;

    //Initialize the variable
    for(v=0;v<G.vexnum;v++)
    {
        final[v]=0;
        D[v]=G.arcs[v0][v].adj;

        for(w=0;w<G.vexnum;w++) //set the empty path
        {
            P[v][w]=0;
        }

        if(D[v]<INT_MAX)  //directed from v to v0
        {
            P[v][v]=1;
            P[v][v0]=1;
        }
    }
    
    final[v0]=1;
    D[v0]=0;
    //Check the remaining vertex node(index starting from 1)
    //Exclude the start point(source point)
    for(i=1;i<G.vexnum;i++)
    {
        min=INT_MAX;

        for(w=0;w<G.vexnum;w++)
        {
            if(!final[w] && D[w]<min)
            {
                v=w; //w is more closer to v0
                min=D[w];
            }
        } 

        final[v]=1;
        /*D[v]=min; */

        for(w=0;w<G.vexnum;w++)
        {
            if (!final[w] && G.arcs[v][w].adj != INT_MAX && G.arcs[v][w].adj + min < D[w])
            {
                D[w] = G.arcs[v][w].adj + min;
                memcpy(P[w],P[v],sizeof(int)*MAX_VERTEX_NUM);
                P[w][w]=1;  //it has on itself                
            }
        }

    }
}
//------------------------------------------//
void Display_ShortestPath(MGraph G, int destination, PathMatrix P, ShortPathTable D)
{
    int w;

    for(w=0;w<G.vexnum;w++)
    {
        if(P[destination][w])
        {
            printf("-%c-",G.vexs[w]);
        }
    }

    printf("\nThe total weight is %d\n", D[destination]);
}
  1. 总结
    Dijkstra 算法是图论中非常关键算法之一,本文主要聚焦于《数据结构》(严蔚敏)提供的算法。后续我们将尝试采用Priority Queue进行算法的实现。

参考文献:
数据结构,严蔚敏

你可能感兴趣的:(算法,数据结构,图论)