本章介绍弗洛伊德算法。和以往一样,本文会先对弗洛伊德算法的理论论知识进行介绍,然后给出C语言的实现。后续再分别给出C++和Java版本的实现。

目录
1. 弗洛伊德算法介绍
2. 弗洛伊德算法图解
3. 弗洛伊德算法的代码说明
4. 弗洛伊德算法的源码

转载请注明出处:http://www.cnblogs.com/skywang12345/

更多内容:数据结构与算法系列 目录

弗洛伊德算法介绍

和Dijkstra算法一样,弗洛伊德(Floyd)算法也是一种用于寻找给定的加权图中顶点间最短路径的算法。该算法名称以创始人之一、1978年图灵奖获得者、斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名。

基本思想

通过Floyd计算图G=(V,E)中各个顶点的最短路径时,需要引入一个矩阵S,矩阵S中的元素a[i][j]表示顶点i(第i个顶点)到顶点j(第j个顶点)的距离。

假设图G中顶点个数为N,则需要对矩阵S进行N次更新。初始时,矩阵S中顶点a[i][j]的距离为顶点i到顶点j的权值;如果i和j不相邻,则a[i][j]=∞。 接下来开始,对矩阵S进行N次更新。第1次更新时,如果"a[i][j]的距离" > "a[i][0]+a[0][j]"(a[i][0]+a[0][j]表示"i与j之间经过第1个顶点的距离"),则更新a[i][j]为"a[i][0]+a[0][j]"。 同理,第k次更新时,如果"a[i][j]的距离" > "a[i][k]+a[k][j]",则更新a[i][j]为"a[i][k]+a[k][j]"。更新N次之后,操作完成!

单纯的看上面的理论可能比较难以理解,下面通过实例来对该算法进行说明。

弗洛伊德算法图解

以上图G4为例,来对弗洛伊德进行算法演示。

初始状态:S是记录各个顶点间最短路径的矩阵。
第1步:初始化S。
    矩阵S中顶点a[i][j]的距离为顶点i到顶点j的权值;如果i和j不相邻,则a[i][j]=∞。实际上,就是将图的原始矩阵复制到S中。
    注:a[i][j]表示矩阵S中顶点i(第i个顶点)到顶点j(第j个顶点)的距离。

第2步:以顶点A(第1个顶点)为中介点,若a[i][j] > a[i][0]+a[0][j],则设置a[i][j]=a[i][0]+a[0][j]。
    以顶点a[1]6,上一步操作之后,a[1][6]=∞;而将A作为中介点时,(B,A)=12,(A,G)=14,因此B和G之间的距离可以更新为26。

同理,依次将顶点B,C,D,E,F,G作为中介点,并更新a[i][j]的大小。

弗洛伊德算法的代码说明

以"邻接矩阵"为例对弗洛伊德算法进行说明,对于"邻接表"实现的图在后面会给出相应的源码。

1. 基本定义

// 邻接矩阵
typedef struct _graph
{
char vexs[MAX]; // 顶点集合
int vexnum; // 顶点数
int edgnum; // 边数
int matrix[MAX][MAX]; // 邻接矩阵
}Graph, *PGraph;

Graph是邻接矩阵对应的结构体。
vexs用于保存顶点,vexnum是顶点数,edgnum是边数;matrix则是用于保存矩阵信息的二维数组。例如,matrix[i][j]=1,则表示"顶点i(即vexs[i])"和"顶点j(即vexs[j])"是邻接点;matrix[i][j]=0,则表示它们不是邻接点。

2. 弗洛伊德算法

/*
* floyd最短路径。
* 即,统计图中各个顶点间的最短路径。
*
* 参数说明:
* G -- 图
* path -- 路径。path[i][j]=k表示,"顶点i"到"顶点j"的最短路径会经过顶点k。
* dist -- 长度数组。即,dist[i][j]=sum表示,"顶点i"到"顶点j"的最短路径的长度是sum。
*/
void floyd(Graph G, int path[][MAX], int dist[][MAX])
{
int i,j,k;
int tmp; // 初始化
for (i = 0; i < G.vexnum; i++)
{
for (j = 0; j < G.vexnum; j++)
{
dist[i][j] = G.matrix[i][j]; // "顶点i"到"顶点j"的路径长度为"i到j的权值"。
path[i][j] = j; // "顶点i"到"顶点j"的最短路径是经过顶点j。
}
} // 计算最短路径
for (k = 0; k < G.vexnum; k++)
{
for (i = 0; i < G.vexnum; i++)
{
for (j = 0; j < G.vexnum; j++)
{
// 如果经过下标为k顶点路径比原两点间路径更短,则更新dist[i][j]和path[i][j]
tmp = (dist[i][k]==INF || dist[k][j]==INF) ? INF : (dist[i][k] + dist[k][j]);
if (dist[i][j] > tmp)
{
// "i到j最短路径"对应的值设,为更小的一个(即经过k)
dist[i][j] = tmp;
// "i到j最短路径"对应的路径,经过k
path[i][j] = path[i][k];
}
}
}
} // 打印floyd最短路径的结果
printf("floyd: \n");
for (i = 0; i < G.vexnum; i++)
{
for (j = 0; j < G.vexnum; j++)
printf("%2d ", dist[i][j]);
printf("\n");
}
}

弗洛伊德算法的源码

这里分别给出"邻接矩阵图"和"邻接表图"的弗洛伊德算法源码。

1. 邻接矩阵源码(matrix_udg.c)

2. 邻接表源码(list_udg.c)

Floyd算法(一)之 C语言详解的更多相关文章

  1. Dijkstra算法(一)之 C语言详解

    本章介绍迪杰斯特拉算法.和以往一样,本文会先对迪杰斯特拉算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 迪杰斯特拉算法介绍 2. 迪杰斯特拉算法 ...

  2. Prim算法(一)之 C语言详解

    本章介绍普里姆算法.和以往一样,本文会先对普里姆算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 普里姆算法介绍 2. 普里姆算法图解 3. 普里 ...

  3. Kruskal算法(一)之 C语言详解

    本章介绍克鲁斯卡尔算法.和以往一样,本文会先对克鲁斯卡尔算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 最小生成树 2. 克鲁斯卡尔算法介绍 3 ...

  4. 原来Github上的README.md文件这么有意思——Markdown语言详解(sublime text2 版本)

    一直想学习 Markdown 语言,想起以前读的一篇 赵凯强 的 博客 <原来Github上的README.md文件这么有意思——Markdown语言详解>,该篇博主 使用的是Mac系统, ...

  5. Java Web----EL(表达式语言)详解

     Java Web中的EL(表达式语言)详解 表达式语言(Expression Language)简称EL,它是JSP2.0中引入的一个新内容.通过EL可以简化在JSP开发中对对象的引用,从而规范页面 ...

  6. 二分算法题目训练(二)——Exams详解

    CodeForces732D——Exams 详解 Exam 题目描述(google翻译) Vasiliy的考试期限将持续n天.他必须通过m门科目的考试.受试者编号为1至m. 大约每天我们都知道当天可以 ...

  7. 最短路径——floyd算法代码(c语言)

    最短路径问题 昨天自己试了试写一下dijkstra的算法博客 dijkstra链接在这← 今天来更floyd算法,感觉非常简单果然暴力才是解决一切的王道 一.总体思想 floyd算法就是每一次从邻接矩 ...

  8. Kruskal算法 - C语言详解

    最小生成树 在含有n个顶点的连通图中选择n-1条边,构成一棵极小连通子图,并使该连通子图中n-1条边上权值之和达到最小,则称其为连通网的最小生成树.  例如,对于如上图G4所示的连通网可以有多棵权值总 ...

  9. 拓扑排序(一)之 C语言详解

    本章介绍图的拓扑排序.和以往一样,本文会先对拓扑排序的理论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 拓扑排序介绍 2. 拓扑排序的算法图解 3. 拓扑 ...

随机推荐

  1. CAS 4.0.0RC 配置通过数据库认证用户登录

    配置通过数据库认证用户登录 打开webapp\WEB-INF目录下的deployerConfigContext.xml,替换 <bean id="primaryAuthenticati ...

  2. DOM技术实现竞赛题页面

    DOM技术实现竞赛题页面 这一段时间学习了DOM操作和JS开发,我就自己开发一个竞赛题的页面. 一.业务需求 1.目标:做一个一百道选择题的页面 2.功能: 显示题目和选项. 下一题上一题的按钮,到第 ...

  3. ecshop数据表说明

    ecshop数据表说明 数据库结构说明,以及自己在后台备份不需要备份的表(红色字体是不需要备份的表)备份文件在FTP或者服务器上网站根目录下data\sqldata下 数据库采用mysql,共78张表 ...

  4. 伪元素小tips

    1.伪元素的是dom看不见的,表现为行内元素.我这里说的伪元素是指::before ::after.其他的像:first-letter :visited 则属于伪类. 2.因为dom不可见,所以伪元素 ...

  5. Linux之RPM安装软件

    源码包 (可以看到源代码)      脚本安装包(写好的xsheel一键安装.本质还是源码包和二进制包) 二进制包(RPM包.系统默认包)      包管理系统简单,通过命令就可以安装.卸载     ...

  6. C#基于Socket的简单聊天室实践

    序:实现一个基于Socket的简易的聊天室,实现的思路如下: 程序的结构:多个客户端+一个服务端,客户端都是向服务端发送消息,然后服务端转发给所有的客户端,这样形成一个简单的聊天室功能. 实现的细节: ...

  7. 【菜鸟玩Linux开发】在C++里操作MySQL

    MySQL是一个的开源关系型数据库,对于服务端开发来说是一个优秀的选择.本篇内容将介绍如何在C++程序里操作MySQL数据库. ———————————————————————————————————— ...

  8. [后端人员耍前端系列]AngularJs篇:30分钟快速掌握AngularJs

    一.前言 对于前端系列,自然少不了AngularJs的介绍了.在前面文章中,我们介绍了如何使用KnockoutJs来打造一个单页面程序,后面一篇文章将介绍如何使用AngularJs的开发一个单页面应用 ...

  9. 返本求源——DOM元素的特性与属性

    抛砖引玉 很多前端类库(比如dojo与JQuery)在涉及dom操作时都会见到两个模块:attr.prop.某天代码复查时,见到一段为某节点设置文本的代码: attr.set(node, 'inner ...

  10. GitHub初体验(小菜新手github用起来)

    记得自己刚认识github的时候觉得他好高端,只知道好多牛人托管代码在上面,但是还觉得离我好遥远.其实不然,用起来,哇塞,真强大. 如果你现在像我当时一样茫然,那希望我的分享能帮助到你.(记录自己用起 ...