Floyd算法思想及实现

  Floyd算法用于求每一对顶点间的最短距离。与Dijkstra算法相比较,时间复杂度均为O(n2),但Floyd算法形式上更简单一些。

一、 Floyd算法的原理

首先记录两点间无其他中间顶点的距离(Vi---Vj),加一个顶点为中间点,记录加一个顶点后两点间的最短距离,以此类推,加完N个顶点后两点间的最短距离即可求出。

二、算法实现

  用三重循环实现。用二维数组表示顶点到顶点的距离。如D[i][j]表示从ij点的距离。第一层循环依次加顶点,第二层循环遍历Vi点,第三层循环遍历Vj点。

/*graph.h文件*/
//---------图的数组(邻接矩阵)存储表示----------
#include<stdio.h>
#include <string.h>
#include <stdlib.h>
#define INFINITY  10000        //最大值
#define MAX_VERTEX_NUM 20        //最大顶点个数  
typedef int VRType;        
typedef char VertexType;    
typedef char InfoType;       
typedef enum{DG,DN,UDG,UDN}  GraphKind; //有向图,有向网,无向图,无向网
typedef struct ArcCell
{
    VRType adj;                            //顶点关系类型,对无权图,有1或0表示是否相邻;对带权图,则为权值类型。
    InfoType *info;                        //弧相关信息的指针
}ArcCell, AdjMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

typedef struct
{
    VertexType vexs[MAX_VERTEX_NUM];       //顶点向量
    AdjMatrix  arcs;                       //邻接矩阵
    int        vexnum,arcnum;              //图的当前顶点数和弧数
}mgraph,*MGraph;

int Locate_vexs(MGraph &g,VertexType v)        //定位顶点位置
{
    for (int i=0;i<g->vexnum;i++)
        if (g->vexs[i]==v)
            return i;
    return -1;
}

void Print_mgraph(MGraph &g)        //打印图
{    
    int i;
    printf("邻接矩阵为:\n");
    printf("");    //五个空格
    for (i=0;i<g->vexnum;i++)
        printf("%c     ",g->vexs[i]);
    printf("\n\n");
    for (i=0;i<g->vexnum;i++)
    {
        printf("%c     ",g->vexs[i]);
        for (int j=0;j<g->vexnum;j++)
        {
            //输出矩阵,并且调整矩阵
            if (g->arcs[i][j].adj>0&&g->arcs[i][j].adj<10)
                printf("%d     ",g->arcs[i][j].adj);
            else if (g->arcs[i][j].adj>9&&g->arcs[i][j].adj<100)
                printf("%d    ",g->arcs[i][j].adj);
            else if (g->arcs[i][j].adj>99&&g->arcs[i][j].adj<1000)
                printf("%d   ",g->arcs[i][j].adj);
            else if (g->arcs[i][j].adj>999&&g->arcs[i][j].adj<10000)
                printf("%d  ",g->arcs[i][j].adj);
            else if(g->arcs[i][j].adj==INFINITY)
                printf("");
        }
        printf("\n\n");
    }    
}

void Add_vexs(MGraph &g)            //增加顶点
{
    printf("请输入顶点个数:");
    scanf("%d",&g->vexnum);
    getchar();//吸收回车符
    printf("请输入顶点字符串序列:");
    for (int i=0;i<g->vexnum;i++)
        scanf("%c",&g->vexs[i]);
}

void Add_arcs(MGraph &g)            //增加边
{
    printf("请输入边的条数:");
    scanf("%d",&g->arcnum);
    VertexType v1,v2;
    int row,col;
    VRType weight;;
    printf("请输入权重和对应顶点,以空格隔开:\n");
    for (int i=0;i<g->arcnum;i++)
    {
        scanf("%d %c %c",&weight,&v1,&v2);
        row=Locate_vexs(g,v1);
        col=Locate_vexs(g,v2);
        g->arcs[row][col].adj=weight;
        
    }
}

void Init_graph(MGraph &g)            //初始化图
{
    g=(MGraph)malloc(sizeof(mgraph));
    g->vexnum=0;
    g->arcnum=0;
    for (int i=0;i<MAX_VERTEX_NUM;i++)
        g->vexs[i]='0';
    for (i=0;i<MAX_VERTEX_NUM;i++)
        for (int j=0;j<MAX_VERTEX_NUM;j++)
        {
            g->arcs[i][j].adj=INFINITY;
            g->arcs[i][j].info=NULL;
        }
}

void Create_mgraph(MGraph &g)        //创建图
{
    Add_vexs(g);
    Add_arcs(g);
}
/*Floyd.cpp文件*/
#include "graph.h"
#define FALSE 0
#define TRUE 1
typedef int DistancMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];        //存放路径长度
typedef int PathMatrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM][MAX_VERTEX_NUM];    
//存放路径,P[0][1][]表示顶点0到顶点1的路径,经过哪个点P[0][1][i]就是TRUE。

void Print_DistancMatrix(MGraph g,DistancMatrix &D)        //打印距离矩阵
{
    int i;
    printf("\t\t距离矩阵为:\n");
    printf("");    //五个空格
    for (i=0;i<g->vexnum;i++)
    {
        printf("%c     ",g->vexs[i]);
    }
    printf("\n\n");
    for (i=0;i<g->vexnum;i++)
    {    
        printf("%c     ",g->vexs[i]);
        for (int j=0;j<g->vexnum;j++)
        {
            if (D[i][j]>0&&D[i][j]<10)
                printf("%d     ",D[i][j]);
            else if (D[i][j]>9&&D[i][j]<100)
                printf("%d    ",D[i][j]);    
            else if (D[i][j]>99&&D[i][j]<1000)
                printf("%d   ",D[i][j]);    
            else if (D[i][j]>999&&D[i][j]<10000)
                printf("%d  ",D[i][j]);    
            else if(D[i][j]==INFINITY)
                printf("");
        }
        printf("\n\n");
    }
    printf("-----------------------------------------\n");
}

void Print_PathMatrix(MGraph g,PathMatrix &P)
{
    int i;
    printf("\t\t最短路径矩阵为:\n");
    for (i=0;i<g->vexnum;i++)
    {
        printf("#######");
        for (int vexcount=0;vexcount<g->vexnum;vexcount++)
        {
            printf("%c     ",g->vexs[vexcount]);
        }
        printf("\n\n");
        for (int j=0;j<g->vexnum;j++)
        {
            printf("%d-->%d: ",i+1,j+1);
            for (int k=0;k<g->vexnum;k++)
            {
                printf("%d     ",P[i][j][k]);
            }
            printf("\n\n");
        }
        printf("-----------------------------------------\n");
    }
}

void ShortestPath_Folyd(MGraph g,PathMatrix &P,DistancMatrix &D)
{    //用Floyd算法求有向网G中各对顶点v和w之间的最短路径P[v][w]及其带权长
    //度D[v][w],若p[v][w][u]为TRUE,则u是从v到w当前求的最短路径上的顶点
    int u,v,w,i;
    for (v=0;v<g->vexnum;++v)        //对各节点之间初始已知路径及距离
        for (w=0;w<g->vexnum;++w)
        {
            D[v][w]=g->arcs[v][w].adj;
            for (u=0;u<g->vexnum;++u)
                P[v][w][u]=FALSE;                    
            if (D[v][w]<INFINITY)        //从v到w有直接路径
            {
                P[v][w][v]=TRUE;        //起点
                P[v][w][w]=TRUE;        //终点
            }//if
        }

        for (u=0;u<g->vexnum;++u)
            for (v=0;v<g->vexnum;++v)
                for (w=0;w<g->vexnum;++w)
                {
                    if(u==v || v==w || w==u)
                        continue;
                    if (D[v][u]+D[u][w]<D[v][w])    //从v经u到w的一条路径更短
                    {
                        D[v][w]=D[v][u]+D[u][w];
                        for (i=0;i<g->vexnum;++i)
                            P[v][w][i]=P[v][u][i]||P[u][w][i];
                    }//if
                }
}//ShortestPath_Floyd

int main()
{
//    freopen("in","r",stdin);//freopen("out","w",stdout);
    MGraph g;
    Init_graph(g);
    Create_mgraph(g);
    Print_mgraph(g);

    DistancMatrix D;
    PathMatrix P;
    ShortestPath_Folyd(g,P,D);

    Print_DistancMatrix(g,D);
    Print_PathMatrix(g,P);
    return 0;
}

输入数据:

 

6
123456
10
5 1 2
7 1 4
4 2 3
8 3 1
9 3 6
5 4 3
6 4 6
5 5 4
3 6 1
1 6 5

执行结果为:

 

posted on 2013-04-12 12:57  Coding for myself  阅读(607)  评论(0编辑  收藏  举报