zoukankan      html  css  js  c++  java
  • 图->最短路径->多源最短路径(弗洛伊德算法Floyd)

    文字描述

      求每一对顶点间的最短路径,可以每次以一个顶点为源点,重复执行迪杰斯特拉算法n次。这样,便可求得每一对顶点之间的最短路径。总的执行时间为n^3。但是还有另外一种求每一对顶点间最短路径的方法,就是弗洛伊德(Floyd)算法,它的时间复杂度也为n^3,但是形式上更简单,其基本思想如下:

      

      如果无法理解上面的文字的话,建议看下代码实现部分,可以更容易理解。

    示意图

     

    算法分析

    时间复杂度为n^3

    代码实现

      1 //
      2 // Created by lady on 19-1-6.
      3 //
      4 
      5 #include <stdlib.h>
      6 #include <stdio.h>
      7 #include <string.h>
      8 
      9 #define INFINITY        100000    //最大值
     10 #define MAX_VERTEX_NUM    20        //最大顶点数
     11 
     12 typedef enum {DG, DN, UDG, UDN} GraphKind; //{有向图,有向网,无向图,无向网}
     13 typedef struct ArcCell{
     14     int weight;    //该弧相关信息的指针
     15 }ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM], PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
     16 typedef struct VertexType{
     17     char data[10];
     18 }VertexType;
     19 typedef struct{
     20     VertexType vexs[MAX_VERTEX_NUM];    //顶点向量
     21     AdjMatrix arcs;        //邻接矩阵
     22     int vexnum, arcnum;    //图的当前顶点数和弧数
     23     GraphKind kind;        //图的种类标志
     24 }MGraph;
     25 
     26 /*
     27  * 根据顶点信息, 返回该顶点在图中的位置, 如果返回-1表示顶点不存在
     28  */
     29 static int LocateVex(MGraph *G, char data[])
     30 {
     31     int i = 0;
     32     for(i=0; i<G->vexnum; i++){
     33         if(!strncmp(G->vexs[i].data, data, strlen(G->vexs[i].data))){
     34             return i;
     35         }
     36     }
     37     return -1;
     38 }
     39 
     40 /*
     41  * 用邻接矩阵作为存储结构,创建有向网
     42  */
     43 static int CreateGraphDN(MGraph *G)
     44 {
     45     printf("用邻接矩阵创建有向网,输入顶点数,弧数:");
     46     G->kind = DN;
     47     scanf("%d,%d", &G->vexnum, &G->arcnum);
     48     if(G->vexnum > MAX_VERTEX_NUM){
     49         printf("错误:顶点数不能超过%d!!
    ", MAX_VERTEX_NUM);
     50         return -1;
     51     }
     52     int i = 0, j = 0, k = 0;
     53     char v1[10] = {0}, v2[10]={0}, info[10] = {0};
     54     char tmp[30] = {0};
     55     for(i=0; i<G->vexnum; i++){
     56         printf("输入第%d个顶点: ", i);
     57         memset(G->vexs[i].data, 0, sizeof(G->vexs[0].data));
     58         scanf("%s", G->vexs[i].data);
     59         for(j=0; j<G->vexnum; j++){
     60             G->arcs[i][j].weight = INFINITY;
     61         }
     62         G->arcs[i][i].weight = 0;
     63     }
     64     for(k=0; k<G->arcnum; k++){
     65         printf("输入第%d条弧(顶点1, 顶点2, 权值): ", k);
     66         memset(tmp, 0, sizeof(tmp));
     67         scanf("%s", tmp);
     68         sscanf(tmp, "%[^','],%[^','],%s[^\n]", v1, v2, info);
     69         i = LocateVex(G, v1);
     70         j = LocateVex(G, v2);
     71         if(i<0 || j<0 || (!atoi(info))){
     72             printf("错误:顶点%s或者%s不存在, 或者权值信息%s不对!
    ", v1, v2, info);
     73             return -1;
     74         }
     75         G->arcs[i][j].weight = atoi(info);
     76     }
     77     return 0;
     78 }
     79 
     80 
     81 static void printMatrix(int vexnum, VertexType vexs[], int (*arcs)[MAX_VERTEX_NUM])
     82 {
     83     int i = 0, j = 0;
     84     printf("	");
     85     for(i=0; i<vexnum; i++){
     86         printf("%s	", vexs[i].data);
     87     }
     88     printf("
    ");
     89     for(i=0; i<vexnum; i++){
     90         printf("%s	", vexs[i].data);
     91         for(j=0; j<vexnum; j++){
     92             if(arcs[i][j] == INFINITY){
     93                 printf("INF	");
     94             }else{
     95                 printf("%d	", arcs[i][j]);
     96             }
     97         }
     98         printf("
    ");
     99     }
    100     return ;
    101 }
    102 static void printArchs(int vexnum, VertexType vexs[], AdjMatrix arcs)
    103 {
    104     int i = 0, j = 0;
    105     printf("	");
    106     for(i=0; i<vexnum; i++){
    107         printf("%s	", vexs[i].data);
    108     }
    109     printf("
    ");
    110     for(i=0; i<vexnum; i++){
    111         printf("%s	", vexs[i].data);
    112         for(j=0; j<vexnum; j++){
    113             if(arcs[i][j].weight == INFINITY){
    114                 printf("INF	");
    115             }else{
    116                 printf("%d	", arcs[i][j].weight);
    117             }
    118         }
    119         printf("
    ");
    120     }
    121     return ;
    122 }
    123 
    124 /*
    125  * 用Floyd算法求有向图G中各顶点v和w之间的最短路径P[v][w]及其
    126  * 带权长度D[v][w]。若P[v][w][u]为1, 则u为从v到w当前求得最短路径上的顶点。
    127  */
    128 void ShortestPath_Floyd(MGraph *G)
    129 {
    130     int u=0, v=0, w=0;
    131     int i=0, j=0;
    132     int P[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    133     int D[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
    134     //各对结点之间初始已知路径和距离
    135     for(v=0; v<G->vexnum; v++){
    136         for(w=0; w<G->vexnum; w++){
    137             D[v][w] = G->arcs[v][w].weight;
    138             for(u=0; u<G->vexnum; u++){
    139                 P[v][w][u] = 0;
    140             }
    141             //从v到w有直接路径
    142             if(D[v][w] < INFINITY){
    143                 P[v][w][v] = 1;
    144                 P[v][w][w] = 1;
    145             }
    146         }
    147     }
    148 
    149     for(u=0; u<G->vexnum; u++){
    150         for(v=0; v<G->vexnum; v++){
    151             for(w=0; w<G->vexnum; w++){
    152                 if( D[v][u]+D[u][w] < D[v][w]){
    153                     //从v经u到w的一条路径更短。
    154                     D[v][w] = D[v][u] + D[u][w];
    155                     for(i=0; i<G->vexnum; i++){
    156                         P[v][w][i] = (P[v][u][i] || P[u][w][i]) ? 1: 0;
    157                     }
    158                 }
    159             }
    160         }
    161     }
    162 
    163     printf("
    打印各个顶点间的最短路径的权值:
    ");
    164     printMatrix(G->vexnum, G->vexs, D);
    165 
    166     printf("
    打印各个顶点间的最短路径的中间结点:
    ");
    167     for(u=0; u<G->vexnum; u++){
    168         for(v=0; v<G->vexnum; v++){
    169             printf("minpath(%d,%s<->%d,%s):", u, G->vexs[u].data, v, G->vexs[v].data);
    170             for(w=0; w<G->vexnum; w++){
    171                 if(P[u][v][w] && (u!=v)){
    172                     printf("%s	", G->vexs[w].data);
    173                 }
    174             }
    175             printf("
    ");
    176         }
    177     }
    178 
    179     return 0;
    180 }
    181 
    182 int main(int argc, int *argv[])
    183 {
    184     //以邻接矩阵为存储结构创建有向网
    185     MGraph G;
    186     if(CreateGraphDN(&G) < 0){
    187         return -1;
    188     }
    189     printf("
    打印该图中的信息:
    ");
    190     printArchs(G.vexnum, G.vexs, G.arcs);
    191     //Floyd弗洛依德算法求多源最短路径
    192     ShortestPath_Floyd(&G);
    193 }
    弗洛依德算法(Floyd)求多源最短路径

    代码运行

    /home/lady/CLionProjects/untitled/cmake-build-debug/untitled
    用邻接矩阵创建有向网,输入顶点数,弧数:3,5
    输入第0个顶点: A
    输入第1个顶点: B
    输入第2个顶点: C
    输入第0条弧(顶点1, 顶点2, 权值): A,B,4
    输入第1条弧(顶点1, 顶点2, 权值): B,A,6
    输入第2条弧(顶点1, 顶点2, 权值): A,C,11
    输入第3条弧(顶点1, 顶点2, 权值): C,A,3
    输入第4条弧(顶点1, 顶点2, 权值): B,C,2
    
    打印该图中的信息:
        A    B    C    
    A    0    4    11    
    B    6    0    2    
    C    3    INF    0    
    
    打印各个顶点间的最短路径的权值:
        A    B    C    
    A    0    4    6    
    B    5    0    2    
    C    3    7    0    
    
    打印各个顶点间的最短路径的中间结点:
    minpath(0,A<->0,A):
    minpath(0,A<->1,B):A    B    
    minpath(0,A<->2,C):A    B    C    
    minpath(1,B<->0,A):A    B    C    
    minpath(1,B<->1,B):
    minpath(1,B<->2,C):B    C    
    minpath(2,C<->0,A):A    C    
    minpath(2,C<->1,B):A    B    C    
    minpath(2,C<->2,C):
    
    Process finished with exit code 0
  • 相关阅读:
    基于ZYNQ XC7Z045 FFG 900的高性能计算模块
    linux TCP数据包封装在SKB的过程分析
    关于 linux中TCP数据包(SKB)序列号的小笔记
    TCP的TIME_WAIT状态
    Linux-2.6.25 TCPIP函数调用大致流程
    Linux 下不经过BIOS重启(i386)
    Linux块设备加密之dm-crypt分析
    Device Mapper 代码分析
    Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 3 部分: Systemtap
    Linux 下的一个全新的性能测量和调式诊断工具 Systemtap, 第 2 部分: DTrace
  • 原文地址:https://www.cnblogs.com/aimmiao/p/10229686.html
Copyright © 2011-2022 走看看