Floyd算法(弗洛伊德算法)

算法描述:

  Floyd算法又称为弗洛伊德算法,插点法,是一种用于寻找给定的加权图中顶点间最短路径的算法。从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归地进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1);又用同样地公式由D(1)构造出D(2);……;最后又用同样的公式由D(n-1)构造出矩阵D(n)。矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后继节点矩阵path来记录两点间的最短路径。

核心思路:通过一个图的权值矩阵求出它的每两点间的最短路径矩阵。

算法过程:

  把图用邻接距阵G表示出来,如果从Vi到Vj有路可达,则G[i,j]=d,d表示该路的长度;否则G[i,j]=无穷大。定义一个距阵D用来记录所插入点的信息,D[i,j]表示从Vi到Vj需要经过的点,初始化D[i,j]=j。把各个顶点插入图中,比较插点后的距离与原来的距离,G[i,j] = min( G[i,j], G[i,k]+G[k,j] ),如果G[i,j]的值变小,则D[i,j]=k。    在G中包含有两点之间最短道路的信息,而在D中则包含了最短通路径的信息。比如,要寻找从V5到V1的路径。根据D,假如D(5,1)=3则说明从V5到V1经过V3,路径为{V5,V3,V1},如果D(5,3)=3,说明V5与V3直接相连,如果D(3,1)=1,说明V3与V1直接相连。

优缺点分析: 
  Floyd算法适用于APSP(All Pairs Shortest Paths),稠密图效果最佳,边权可正可负。此算法简单有效,由于三重循环结构紧凑,对于稠密图,效率要高于执行|V|次Dijkstra算法。  
  优点:容易理解,可以算出任意两个节点之间的最短距离,代码编写简单;  
  缺点:时间复杂度为O(n3),比较高,不适合计算大量数据。

代码实现:

#include <stdio.h>
#include <stdlib.h>
#define MAXVERTEX 8
#define INF 65535
typedef char VertexType;
typedef int EdgeType;
typedef struct MGraph
{
    VertexType vertex[MAXVERTEX];
    EdgeType edge[MAXVERTEX][MAXVERTEX];
    int numvex;
    int numedge;
}MGraph;

static int D[MAXVERTEX][MAXVERTEX];
static int P[MAXVERTEX][MAXVERTEX];

void CreateMGraph(MGraph *G)
{
    int i = 0,j = 0,k = 0,w = 0;
    VertexType c;
    printf("请输入顶点数和边数:\n");
    scanf("%d,%d",&G->numvex,&G->numedge);
    for(i = 0;i < G->numvex;i++)
    {
        for(j = 0;j < G->numvex;j++)
        {
           if(i == j)
           {
               G->edge[i][j] = 0;
           }
           else
           {
               G->edge[i][j] = INF;
           }
        }
    }
    printf("请输入顶点的值:\n");
    fflush(stdin);
    scanf("%c",&c);
    while(i < G->numvex)
    {
        if(c == ‘\n‘)
            break;
        else
        {
            G->vertex[i] = c;
            i++;
            scanf("%c",&c);
        }
    }
    fflush(stdin);
    for(k = 0;k < G->numedge;k++)
    {
        printf("请输入边vi-vj所依附的顶点下标 i 和 j,以及权重w:\n");
        scanf("%d,%d,%d",&i,&j,&w);
        G->edge[i][j] = w;
        G->edge[j][i] = G->edge[i][j];
    }
}

void Floyd(MGraph *G)
{
    int i,j,k;
    //初始化
    for(i = 0;i < G->numvex;i++)
    {
        for(j = 0;j < G->numvex;j++)
        {
            D[i][j] = G->edge[i][j];
            P[i][j] = j;
        }
    }
    for(k = 0;k < G->numvex;k++)
    {
        for(i = 0;i < G->numvex;i++)
        {
            for(j = 0;j < G->numvex;j++)
            {
                if(D[i][j] > D[i][k] + D[k][j])
                {
                    D[i][j] = D[i][k] + D[k][j];
                    P[i][j] = P[i][k];
                }
            }
        }
    }
    printf("\n P矩阵为:\n");
    for(i = 0;i < G->numvex;i++)
    {
        for(j = 0;j < G->numvex;j++)
        {
           printf("%d ",P[i][j]);
        }
        printf("\n");
    }
}
void PrintPath(MGraph *G)
{
    int i,j,k;
    for(i = 0;i < G->numvex;i++)
    {
        for(j = i+1;j < G->numvex;j++)
        {
            printf("V%d-V%d minimum weight:%d  ",i,j,D[i][j]);
            k = P[i][j];
            printf("Path: V%d",i);
            while(k != j)
            {
                printf("-->V%d",k);
                k = P[k][j];
            }
            printf("-->V%d\n",j);
        }
        printf("\n");
    }
}

int main()
{
    MGraph G;
    CreateMGraph(&G);
    Floyd(&G);
    PrintPath(&G);
    return 0;
}

  

时间: 2024-10-15 19:07:39

Floyd算法(弗洛伊德算法)的相关文章

Floyd(弗洛伊德算法)---每对顶点的最短路径---《数据结构》严蔚敏

// exam1.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <iostream> #include <stack> using namespace std; #define MAXVEX 20 #define INT_MAX 10000 typedef struct ArcNode { int adj; void* info; }ArcNode; typedef ArcNode AdjMat[MAX

最短路径算法——弗洛伊德算法(Floyd)

算法的本质 用三重循环来清算每个点 对 缩小相邻任意"点对儿"距离的贡献 即每个顶点都有可能使得另外两个顶点之间的距离变短 贡献核心在于两边之和大于第三边 清算完成后即得任意两点的最短路径 算法的基本思想 最开始只允许经过1号顶点进行中转 接下来只允许经过1和2号顶点进行中转 -- 允许经过1~n号所有顶点进行中转 求任意两点之间的最短路程 用一句话概括就是:从i号顶点到j号顶点只经过前k号点的最短路程 其实这是一种"动态规划"的思想 C语言伪代码表示的算法 voi

图的算法---弗洛伊德算法

int main() { int e[10][10],k,i,j,n,m,t1,t2,t3; int inf=99999999; //用inf(infinity的缩写)存储一个我们认为的正无穷值 //读入n和m,n表示顶点个数,m表示边的条数 scanf("%d %d",&n,&m); //初始化 for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i==j) e[i][j]=0; else e[i][j]=inf; //读入边 f

最短路径之弗洛伊德算法(Floyd)

Floyd算法又称为插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法. 路径矩阵 通过一个图的权值矩阵求出它的每两点间的最短路径矩阵. 从图的带权邻接矩阵A=[a(i,j)] n×n开始,递归的进行n次更新,即由矩阵D(0)=A,按一个公式,构造出矩阵D(1): 又用同样地公式由D(1)构造出D(2):--:最后又用同样的公式由D(n-1)构造出矩阵D(n).矩阵D(n) 的 i 行 j 列元素便是 i 号顶点到 j 号顶点的最短路径长度,称D(n)为图的距离矩阵,同时还可引入一个后

数据结构之---C语言实现最短路径之Floyd(弗洛伊德)算法

//此代码综合网络上的代码. //弗洛伊德算法Floyd代码 //杨鑫 #include <stdio.h> #include <stdlib.h> #define MAX_VERTEX_NUM 100 //最大顶点数 #define MAX_INT 10000 //无穷大 typedef int AdjType; typedef struct { int pi[MAX_VERTEX_NUM]; //存放v到vi的一条最短路径 int end; }PathType; typedef

两点之间最短路径:弗洛伊德算法

弗洛伊德算法是计算无向有权图中两点间最短路径的算法,复杂度为O(n^3).其思路是将两点间距离分为过(指定的)第三点或是不过,然后取它们的最小值,如此循环就可以得到两点之间真正的最小值. void floyd() { for (int k = 0; k < n; ++k) { for (int i = 0; i < n; ++i) { for (int j = 0; j < n; ++j) { //在当前i到j经过k点的路径与直连的路径中选最短 matrix[i][j] = min(ma

Floyd判圈算法

Floyd判圈算法(Floyd Cycle Detection Algorithm),又称龟兔赛跑算法(Tortoise and Hare Algorithm),是一个可以在有限状态机.迭代函数或者链表上判断是否存在环,求出该环的起点与长度的算法.该算法据高德纳称由美国科学家罗伯特·弗洛伊德发明,但这一算法并没有出现在罗伯特·弗洛伊德公开发表的著作中.  如果有限状态机.迭代函数或者链表上存在环,那么在某个环上以不同速度前进的2个指针必定会在某个时刻相遇.同时显然地,如果从同一个起点(即使这个起

【啊哈!算法】算法6:只有五行的Floyd最短路算法

暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程. 上图中有4个城市8条公路,公路上的数字表示这条公路的长短.请注意这些公路是单向的.我们现在需要求任意两个城市之间的最短路程,也就是求任意两个点之间的最短路径.这个问题这也被称为“多源最短路径”问题. 现在需要一个数据结构来存储图的信息,我们仍然可以用一个4*4的矩阵(二维数组e)来存储.比如1号城市到2号城市的路程为2,则设e[1][2]

数据结构(五)图---最短路径(弗洛伊德算法)

一:定义 弗洛伊德算法是用来求所有顶点到所有顶点的时间复杂度. 虽然我们可以直接对每个顶点通过迪杰斯特拉算法求得所有的顶点到所有顶点的时间复杂度,时间复杂度为O(n*3),但是弗洛伊德算法更加简洁优雅 二:弗洛伊德的使用介绍 若是求一个顶点到其他顶点的最短距离,例如迪杰斯特拉算法,我们的距离数组和路径数组使用一维即可,但是我们这里是获取所有顶点到其余顶点的最短距离,所以我们对于数组和路径都需要使用二维数组来表示 下面我们使用一个有三个顶点的图来进行讲解: (1)我们先定义两个二维数组D0[3][