• 算法学习记录图——最小路径之Floyd算法


    floyd算法:

    解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。

    D_{i,j,k}为从ij的只以(1..k)集合中的节点为中间节点的最短路径的长度。

    1. 若最短路径经过点k,则D_{i,j,k}=D_{i,k,k-1}+D_{k,j,k-1}
    2. 若最短路径不经过点k,则D_{i,j,k}=D_{i,j,k-1}

    因此,D_{i,j,k}=\mbox{min}(D_{i,k,k-1}+D_{k,j,k-1},D_{i,j,k-1})

    在实际算法中,为了节约空间,可以直接在原来空间上进行迭代,这样空间可降至二维。

    我的理解为:

    folyd算法是每次选定一个点,查看任意两个顶点的距离是否都小于经过这个点之和的距离。

    即:假如ABC三个顶点相连,选定C的时候,查AB的距离是否大于 AC + CB 的距离之和,

    如果大于说明找到了一个更短的路径,即A->C->B。

    下面是我的例子:

     

     floyd算法是一个动态规划的过程,可以上网查下图中中关于它的证明。

     代码:

    void floyd(MGraph g,EdgeType *des,EdgeType *path)
    {
        //初始化 des,path
        int i,j;
    
        for (i=0;i<g.numVexs;i++)
        {
            for (j=0;j<g.numVexs;j++)
            {
                *(des + i*MAXVEX +j) = g.Mat[i][j];
                *(path + i*MAXVEX +j) = j;
            }
        }
    
        int k;
        for (k=0;k<g.numVexs;k++)
        {
            for (i=0;i<g.numVexs;i++)
            {
                for (j=0;j<g.numVexs;j++)
                {
                    //printf("[%d][%d]---%d  [%d][%d]+[%d][%d]---%d\n", i,j,*(des +i*MAXVEX +j),i,k,k,j,g.Mat[i][k] + g.Mat[k][j]);
                    if ( *(des +i*MAXVEX +j) > *(des +i*MAXVEX +k) + *(des + k*MAXVEX + j))
                    {
                        
                        *( des + i*MAXVEX +j ) = *(des +i*MAXVEX +k) + *(des + k*MAXVEX + j);
                        *( path + i*MAXVEX + j ) = *(path+i*MAXVEX +k);
                    }
                }
            }
            if (k == 5)
            {
                break;
            }
        }
    }

    第一个for是初始化,第二个for快里面嵌入2个for循环,三个for循环完成最短路径的查找,算法很神奇。

    调用后,我给出的结果是一个矩阵形式:

    在Dest中,表示v0(A)到其他点的最短距离,和之前的Dijkstra算法对顶点A的结果一致。其他行类推。

    在Edge中,由于点初始化的时候,每个点写入的是自己,这样在查看最短路径的时候,这样看

    比如查找v0->v8的最小路径,查看第一行(v0)的第八行(v8):显示是1,表示到v8点,需要经过v1,

    再查看第二行(v1)到v8的值:2,,表示v1到v8需要经过v2。。。依次类推。

    v0到v8的路径为:

    v0->1->v2->v4->v7->v8

    可以写一个代码来显示最短路径:

    void prt_short_path(int vs,int ve,EdgeType *p)
    {
        int x = vs;
        printf(" %c --> ",g_init_vexs[x]);
        while(x != ve)
        {
            x = *(p + MAXVEX*x + ve);
            printf(" %c --> ",g_init_vexs[x]);
        }
    }

    完整代码:

    // grp-dijkstra.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <stdlib.h>
    #include <string.h>
    
    
    #define MAXVEX 100
    #define IFY 65535
    
    typedef char VertexType;
    typedef int  EdgeType;
    
    
    bool g_visited[MAXVEX];
    
    VertexType g_init_vexs[MAXVEX] = {'A','B','C','D','E','F','G','H','I'};
    
    EdgeType g_init_edges[MAXVEX][MAXVEX] = {
        {0,2,5,IFY,IFY,IFY,IFY,IFY,IFY},    //'A'
        {2,0,2,8,5,IFY,IFY,IFY,IFY},  //'B'
        {5,2,0,IFY,1,6,IFY,IFY,IFY},//'C'
        {IFY,8,IFY,0,3,IFY,2,IFY,IFY},//'D'
        {IFY,5,1,3,0,5,8,7,IFY},    //'E'
        {IFY,IFY,6,IFY,5,0,IFY,4,IFY},    //'F'
        {IFY,IFY,IFY,2,8,IFY,0,2,9},    //'G'
        {IFY,IFY,IFY,IFY,7,4,2,0,3},    //'H'
        {IFY,IFY,IFY,IFY,IFY,IFY,9,3,0},    //'I'
    };
    
    
    //静态图-邻接矩阵
    typedef struct {
        VertexType vexs[MAXVEX];
        EdgeType Mat[MAXVEX][MAXVEX];
        int numVexs,numEdges;
    }MGraph;
    
    
    //====================================================================
    //打印矩阵
    void prt_maxtix(EdgeType *p,int vexs)
    {
        int i,j;
        for (i=0;i<vexs;i++)
        {
            printf("\t");
            for (j=0;j<vexs;j++)
            {
                if( (*(p + MAXVEX*i + j)) == IFY)
                {
                    printf("  $ ");
                }
                else
                {
                    printf(" %2d ", *(p + MAXVEX*i + j));
                }
            }
            printf("\n");
        }
    }
    
    //check the number of vextex
    int getVexNum(VertexType *vexs)
    {
        VertexType *pos = vexs;
        int cnt=0;
        while(*pos <= 'Z' && *pos >= 'A')
        {
            cnt++;
            pos++;
        }
        return cnt;
    }
    
    bool checkMat(EdgeType *p,VertexType numvex)
    {
        int i,j;
        for (i=0;i<numvex;i++)
        {
            for(j=i+1;j<numvex;j++)
            {
                //printf("[%d][%d] = %d\t",i,j,*(p + MAXVEX*i + j));
                //printf("[%d][%d] = %d\n",j,i,*(p + MAXVEX*j + i));
                if (*(p + MAXVEX*i + j) != *(p + MAXVEX*j +i) )
                {
                    printf("ERROR:Mat[%d][%d] or Mat[%d][%d] not equal!\n",i,j,j,i);
                    return false;
                }
            }
        }
        return true;
    }
    
    void init_Grp(MGraph *g,VertexType *v,EdgeType *p)
    {
        int i,j;
        // init vex num
        (*g).numVexs = getVexNum(v);
    
        //init vexter 
        for (i=0;i<(*g).numVexs;i++)
        {
            (*g).vexs[i]=*v;
            v++;
        }
    
        //init Mat 
        for (i=0;i<(*g).numVexs;i++)
        {
            for (j=0;j<(*g).numVexs;j++)
            {
                (*g).Mat[i][j] = *(p + MAXVEX*i + j);
            }
        }
        if(checkMat(&((*g).Mat[0][0]),(*g).numVexs) == false)
        {
            printf("init error!\n");
            getchar();
            exit(0);
        }
    }
    
    void init_path(EdgeType *p,int num)
    {
        int i,j;
        for (i=0;i<num;i++)
        {
            for (j=0;j<num;j++)
            {
                *(p + i*MAXVEX + j) = j; 
            }
        }
    }
    
    void floyd(MGraph g,EdgeType *des,EdgeType *path)
    {
        //初始化 des,path
        int i,j;
    
        for (i=0;i<g.numVexs;i++)
        {
            for (j=0;j<g.numVexs;j++)
            {
                *(des + i*MAXVEX +j) = g.Mat[i][j];
                *(path + i*MAXVEX +j) = j;
            }
        }
    
        int k;
        for (k=0;k<g.numVexs;k++)
        {
            for (i=0;i<g.numVexs;i++)
            {
                for (j=0;j<g.numVexs;j++)
                {
                    //printf("[%d][%d]---%d  [%d][%d]+[%d][%d]---%d\n", i,j,*(des +i*MAXVEX +j),i,k,k,j,g.Mat[i][k] + g.Mat[k][j]);
                    if ( *(des +i*MAXVEX +j) > *(des +i*MAXVEX +k) + *(des + k*MAXVEX + j))
                    {
                        
                        *( des + i*MAXVEX +j ) = *(des +i*MAXVEX +k) + *(des + k*MAXVEX + j);
                        *( path + i*MAXVEX + j ) = *(path+i*MAXVEX +k);
                    }
                }
            }
            
        }
    }
    void prt_short_path(int vs,int ve,EdgeType *p)
    {
        int x = vs;
        printf(" %c --> ",g_init_vexs[x]);
        while(x != ve)
        {
            x = *(p + MAXVEX*x + ve);
            printf(" %c --> ",g_init_vexs[x]);
        }
    }
    int _tmain(int argc, _TCHAR* argv[])
    {
        MGraph grp;
    
        EdgeType edgeDest[MAXVEX][MAXVEX];
        EdgeType edgePath[MAXVEX][MAXVEX];
    
        int i;
    
        init_Grp(&grp,g_init_vexs,&g_init_edges[0][0]);
        prt_maxtix(&grp.Mat[0][0],grp.numVexs);
        printf("Floyd start!\n");
        floyd(grp,&edgeDest[0][0],&edgePath[0][0]);
    
        printf("Dest:\n");
        prt_maxtix(&edgeDest[0][0],grp.numVexs);
        
        printf("Edge:\n");
        prt_maxtix(&edgePath[0][0],grp.numVexs);
        
    
        prt_short_path(0,8,&edgePath[0][0]);
        printf("finish\n");
        getchar();
        return 0;
    }
  • 相关阅读:
    mysql重置id
    mysql数据类型
    手把手教你新建一个Vue项目
    用markdown开始优雅的写作
    源码阅读心得
    断点调试-程序员的必修课
    代码还是短点好!
    GoJS v1.8.27 去水印方法
    VS code不用集成终端如何修改并推送分支?
    LeetCode日拱一卒
  • 原文地址:https://www.cnblogs.com/jsgnadsj/p/3427817.html
Copyright © 2020-2023  润新知