回 帖 发 新 帖 刷新版面

主题:[原创]Dijkstra算法实现(ANSI C)(08.6.7更新:配对堆实现)

一、Dijkstra算法的基本思想
    
    首先引进一个辅助向量D,其每个分量D[]表示当前阶段从起点start到顶点i所计算出的最短路径。初始化之为:D[start]为0,其余D[]为“无穷大”。
    在每个阶段,该算法选择所有顶点中D[]最小的未知顶点,将其标记为已知,然后对其所有的邻接顶点的D[]进行更新(若新的D[]更小的话),然后进入下一阶段,直至所有顶点均已知。
    
    为什么这样做是对的?
    令某阶段下所有的已知顶点构成集合S,则当前阶段选择的D[]最小的v的最短路径上的点必然存在于S中。
    用反证法来证明之之:
    算法是按照路径长度的递增来构成S,假设v的最短路径L上有一点w不在S内,即w是一个未知顶点。
    1.因为w处于L上,所以start到w路径要比L短。得出 D[w] < D[v]
    2.v是当前阶段选择的D[]最小的未知点,故 D[w] > D[v]
    结论1和结论2相悖。所以刚才的假设错误。此反证法证明了Dijkstra算法的正确性。

二、伪代码

Dijsktra( D, G, start )
{
        Init D[];
        while ( select an unknown v which has a smallest D[v] )
        {
                for each w adjacent of v
                {
                        if ( D[w] will be smaller )
                        {
                                update D[w];
                        }
                }
        }
}

三、ANSI C 代码

typedef int Bool;
#define TRUE  ( 1 )
#define FALSE ( 0 )

#define NULL             ( 0 )
#define NOT_A_VERTEX     ( 0 )
#define INFINITY         ( 0xFFFFFFF )
#define MAX_NUM_VERTICES ( 100 )

/* use adjacent list to represent a graph */
/* Vertices are numbered from 1 */
/* 0 express an inexistent vertex */
typedef int Weight;
typedef unsigned int Vex;
typedef struct edge
{
        Vex vex;
        Weight weight;
        struct edge* next;
}* Edge;
typedef struct vertex
{
        Edge first;
}* Vertex;
typedef struct graph
{
        Vertex vertices[MAX_NUM_VERTICES];
        int num_vertices;
}* Graph;

/* select an unknown vertex which has a smallest D[] */
/* if there are not unknows vertices, it will return NOT_A_VERTEX */
Vex Select( Weight D[], Bool known[], int n );

/* Dijkstra's Algorithm */
/* D[i] will be the weight of the Shorest-Path from start to i */
/* P[i][] will contain all the vertices on the Shorest-Path from start to i */
/* the Shorteset-Path in P[][] will be ended by 0 */
void Dijkstra(  Weight D[], Vex P[][MAX_NUM_VERTICES], Graph G, Vex start )
{
        Bool known[MAX_NUM_VERTICES] = { FALSE };
        Vex* tailP[MAX_NUM_VERTICES] = { NULL  }; /* use to update P[][] */

        Vex v;
        int i;
        Edge edge = NULL;

        /* Initialize D[], P[] and tailP[] */
        for ( v = 1; v <= G->num_vertices; ++v )
        {
                D[v] = INFINITY;
                for ( i = 0; i < MAX_NUM_VERTICES; ++i )
                {
                        P[v][i] = 0;
                }
                tailP[v] = P[v];
        }
        D[start] = 0;

        /* start Dijkstra */
        while ( ( v = Select( D, known, G->num_vertices ) ) != NOT_A_VERTEX )
        {
                *tailP[v] = v;
                known[v] = TRUE;

                /* update each vex adjacent to v if it need to be updated */
                for ( edge = G->vertices[v]->first; edge != NULL; edge = edge->next )
                {
                        if ( ( D[v] + edge->weight ) < D[edge->vex] )
                        {
                                D[edge->vex] = ( D[v] + edge->weight );
                                *tailP[edge->vex]++ = v; /* update P[][] */ 
                        }
                }
        }
        return;
}

/* select an unknown vertex which has a smallest D[] */
/* if there are not unknows vertices, it will return NOT_A_VERTEX */
Vex Select( Weight D[], Bool known[], int n )
{
        Vex v, w;
        Weight min = INFINITY;
        
        v = NOT_A_VERTEX;
        for ( w = 1; w <= n; ++w )
        {
                if ( !known[w] && ( D[w] < min ) )
                {
                        v = w;
                        min = D[w];
                }
        }
        return v;
}

四、该算法时间复杂的分析

    外循环每个顶点要选取并标记一次 O(|V|),求D[]最小的未知顶点要遍历所有点 O(|V|),每个点对周围点更新等于遍历所有的弧 O(|E|)
    所以该算法总时间复杂度 O(|V|^2+|E|)

回复列表 (共11个回复)

11 楼

自己顶一下~~~

我来回复

您尚未登录,请登录后再回复。点此登录或注册