zoukankan      html  css  js  c++  java
  • 最短路径算法——迪杰斯特拉(Dijkstra)

    算法思想


    • 设G=(V,E)是一个带权有向图
    • 把图中顶点集合V分成两组
    • 第一组为已求出最短路径的顶点集合(用S表示,初始时S中只有一个源点,以后每求得一条最短路径 , 就将加入到集合S中,直到全部顶点都加入到S中,算法就结束了)
    • 第二组为其余未确定最短路径的顶点集合(用U表示)
    • 按最短路径长度的递增次序依次把第二组的顶点加入S中
    • 在加入的过程中,总保持从源点v到S中各顶点的最短路径长度不大于从源点v到U中任何顶点的最短路径长度
    • 此外,每个顶点对应一个距离,S中的顶点的距离就是从源点v到此顶点的最短路径长度
    • U中的顶点的距离,是从源点v到此顶点只包括S中的顶点为中间顶点的当前最短路径长度

    C语言伪代码描述的迪杰斯特拉算法


    void ShortestPath_DIJ( MGraph G, int v0, PathMatrix &P, ShortPathTable &D){
        // 用Dijkstra算法求有向网G的v0顶点到其余顶点v的最短路径P[v]及其带权长度D[v]。
        // 若P[v][w]为TRUE,则w是从v0到v当前求得最短路径上的顶点。
        // final[v]为TRUE当且仅当v∈S,即已经求得从v0到v的最短路径。
        for (v = 0; v < G.vexnum; ++ v){
            final[v] = FALSE; D[v] = G.arcs[v0][v];
            for (w = 0; w < G.vexnum; ++ ww) P[v][w] = FALSE;// 设空路径
            if (D[v] < INFINITY) {P[v][v0] = TRUE; P[v][v] = TRUE;}
        }// for
        D[v0] = 0; final[v0] = TRUE;// 初始化,v0顶点属于S集
        // 开始主循环,每次求得v0到某个v顶点的最短路径,并加v到S集
        for (i = 1; i < G.vexnum; ++ i) {// 其余G.vexnum - 1个顶点
            min = INFINITY;// 当前所知离v0顶点的最近距离
            for (w = 0; w < G.vexnum; ++ w)
                if(!final[w])// w顶点在V-S中
                    if(D[w] < min) {v = w; min = D[w];}// w顶点离v0顶点更近
            final[v] = TRUE;// 离v0顶点最近的v加入S集
            for(w = 0; w < G.vexnum; ++ w)// 更新当前最短路径及距离
                if(!final[w] && (min + G.arcs[v][w] < D[w])){// 修改D[w]和P[w],x∈V-S
                    D[w] = min + G.arcs[v][w];
                    P[w] = P[v]; P[w][w] = TRUE;// P[w] = P[v] + P[w]
                }// if
        }// for
    
    }// ShortestPath_DIJ
    

    C语言程序描述的算法


    void Dijkstra(float cost[][n], int v){
        // 求源点v到其余顶点的最短路径及其长度,cost为有向网的带权邻接矩阵
        // 设max值为32767,代表一个很大的数
        v1 = v - 1;
        for(i = 0; i < n; i ++){
            dist[i] = cost[v1][i];// 初始化dist
            if(dist[i] < max) pre[i] = v; else pre[i] = 0;
        }
        pre[v1] = 0;
        for(i = 0; i < n; i ++) S[i] = 0;// 第一组开始为空集
        S[v1] = 1;// 源点v并入第一组
        for(i = 0; i < n; i ++){// 扩充第一组
            min = max;
            for(j = 0; j < n; j ++)
                if(!S[j] && (dist[j] < min)) {min = dist[j]; k = j;}
            S[k] = 1;// 将k+1加入第一组
            for(j = 0; j < n; j ++)
                if(!S[j] && (dist[j] > dist[k] + cost[k][j])){// 修正第二组各顶点的距离值
                    disk[j] = disk[k] + cost[k][j]; pre[j] = k + 1;// k + 1是j + 1的前趋
                }// 所有顶点均已扩充到S中
            for(j = 0; j < n; j ++){// 打印结果
                printf("%f
    %d", dist[i], i + 1);
                p = pre[i];
                while(p != 0){// 继续找前趋顶点
                    printf("<--%d", p);
                    p = pre[p - 1];
                }
            }
        }// Dijkstra
    
    }
    
  • 相关阅读:
    转载一篇 Linux 命令总结
    Linux 常用命令学习
    frp 使用
    Anaconda使用记录
    Linux 学习
    lnmp下django学习
    lnmp安装学习
    学习DHT内容
    pyqt5配置
    MyBatisPlus 常用知识点总结
  • 原文地址:https://www.cnblogs.com/freelancy/p/7940514.html
Copyright © 2011-2022 走看看