算法学习记录图——最小路径之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;
}
原文地址:https://www.cnblogs.com/jsgnadsj/p/3427817.html