最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言

最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第1张图片
最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第2张图片
最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第3张图片

一、无权图的单源最短路算法

最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第4张图片

void Unweighted(LGraph Graph, int dist[], int path[], Vertex S)
{
    Queue Q;
    Vertex V;
    PtrToAdjVNode W;
    
    Q = CreateQueue(Graph->Nv);   // 创建空队列,MaxSize为外部定义的常数
    dist[S] = 0;   // 初始化源点
    AddQ(Q, S);
    
    while (!IsEmpty(Q)) {
        V = DeleteQ(Q);
        for (W=Graph->G[V].FirstEdge; W; W=W->Next)   // 对V的每个邻接点W->AdjV
        if (dist[W->AdjV]==-1) {   // 若W->AdjV未被访问过
            dist[W->AdjV] = dist[V] + 1;   // W->AdjV到S的距离更新
            path[W->AdjV] = V;   // 将V记录在S到W->AdjV的路径上
            AddQ(Q, W->AdjV);
        }
    }   // while结束
}
  • 图的定义(邻接矩阵&邻接表) | C语言

二、有权图的单源最短路算法

2.1 Djkstra

最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第5张图片

  • 伪码描述
    最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第6张图片

(1)初始化,将所有顶点的dist设置为 ∞ \infin ,path设置为-1;
最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第7张图片
然后设置 v 1 v_1 v1的dist为0, v 2 v_2 v2的dist为2,path为1, v 4 v_4 v4的dist为1,path为1;
最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第8张图片
(2)正式进入Dijkstra算法,找到 v 4 v_4 v4,并收录它,分别更新未收录的 v 3 v_3 v3 v 5 v_5 v5 v 6 v_6 v6 v 7 v_7 v7的dist值为3,3,9,5,并更新他们的path都为4;
最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第9张图片
(3)找到未收录顶点中dist最小者为 v 2 v_2 v2,收录它,由于它的邻接点都不符合循环的要求,未做任何更新;
最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第10张图片
(4)找到未收录顶点中dist最小者为 v 3 v_3 v3 v 5 v_5 v5也可以),收录它,由于它的邻接点 v 6 v_6 v6符合要求,将 v 6 v_6 v6的dist从9更新为8,path从4更新为3;
最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第11张图片
(5)重复上述操作,直至所有顶点被收录,相应的dist和path都被更新完成,退出程序;
最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第12张图片

  • 代码
Vertex FindMinDist(MGraph Graph, int dist[], int collected[])
{   // 返回未被收录顶点中dist最小者
    Vertex MinV, V;
    int MinDist = INFINITY;
    
    for (V=0; V<Graph->Nv; V++) {
        if (collected[V]==false && dist[V]<MinDist) {
            // 若V未被收录,且dist[V]更小
            MinDist = dist[V];   // 更新最小距离
            MinV = V;   // 更新对应顶点
        }
    }
    if (MinDist < INFINITY)   // 若找到最小dist
        return MinV;   // 返回对应的顶点下标
    else
        return EROOR;  // 若这样的顶点不存在,返回错误标记
}

bool Dijkstra(MGraph Graph, int dist[], int path[], Vertex S)
{
    int collected[MaxVertexNum];
    Vertex V, W;
    
    // 初始化:此处默认邻接矩阵中不存在的边用INFINITY表示
    for ( V=0; V<Graph->Nv; V++ ) {
        dist[V] = Graph->G[S][V];
        if ( dist[V]<INFINITY )
            path[V] = S;
        else
            path[V] = -1;
        collected[V] = false;
    }
    // 先将起点收入集合
    dist[S] = 0;
    collected[S] = true;
    
    while (1) {
        // V = 未被收录顶点中dist最小者
        V = FindMinDist(Graph, dist, collected);
        if ( V==ERROR )   // 若这样的V不存在
            break;      // 算法结束
        collected[V] = true;   // 收录V
        for ( W=0; W<Graph->Nv; W++ ) {   // 对图中的每个顶点W
            // 若W是V的邻接点并且未被收录
            if ( collected[W]==false && Graph->G[V][W]<INFINITY) {
                if ( Graph->G[V][W]<0 ) {   // 若有负边
                    return false;   // 不能正确解决,返回错误标记
                }
                // 若收录使得dist[W]变小
                if ( dist[V]+Graph->G[V][W] < dist[W] ) {
                    dist[W] = dist[V] + Graph->G[V][W];   // 更新dist[W]
                    path[W] = V;   // 更新S到W的路径
                }
            }
        }
    }   // while 结束
    return true;   // 算法执行完毕,返回正确标记
}

2.2 Floyd

最短路径 | 单源(Dijkstra算法)& 多源(Floyd算法) |C语言_第13张图片

bool Floyd( MGraph Graph, WeightType D[][MaxVertexNum], Vertex path[][MaxVertexNum])
{
    Vertex i, j, k;
    
    // 初始化
    for ( i=0; i<Graph->Nv; i++ ) {
        for ( j=0; j<Graph->Nv; j++) {
            D[i][j] = Graph->G[i][j];
            path[i][j] = -1;
        }
    }
    
    for ( k=0; k<Graph->Nv; k++) {
        for ( i=0; i<Graph->Nv; i++ ) {
            for ( j=0; j<Graph->Nv; j++ ) {
                if ( D[i][k] + D[k][j] < D[i][j] ) {
                    D[i][j] = D[i][k] + D[k][j];
                    if ( i==j && D[i][j]<0)  // 若发现负值圈
                        return false;   // 不能正确解决,返回错误标记
                    path[i][j] = k;
                }
            }
        }
    } // for循环结束
    
    return true;   // 算法执行完毕,返回正确标记
}

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