floyd算法:

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

设为从到的只以集合中的节点为中间节点的最短路径的长度。

  1. 若最短路径经过点k,则;
  2. 若最短路径不经过点k,则。

因此,。

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

我的理解为:

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=;i<g.numVexs;i++)
{
for (j=;j<g.numVexs;j++)
{
*(des + i*MAXVEX +j) = g.Mat[i][j];
*(path + i*MAXVEX +j) = j;
}
} int k;
for (k=;k<g.numVexs;k++)
{
for (i=;i<g.numVexs;i++)
{
for (j=;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 == )
{
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] = {
{,,,IFY,IFY,IFY,IFY,IFY,IFY}, //'A'
{,,,,,IFY,IFY,IFY,IFY}, //'B'
{,,,IFY,,,IFY,IFY,IFY},//'C'
{IFY,,IFY,,,IFY,,IFY,IFY},//'D'
{IFY,,,,,,,,IFY}, //'E'
{IFY,IFY,,IFY,,,IFY,,IFY}, //'F'
{IFY,IFY,IFY,,,IFY,,,}, //'G'
{IFY,IFY,IFY,IFY,,,,,}, //'H'
{IFY,IFY,IFY,IFY,IFY,IFY,,,}, //'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=;i<vexs;i++)
{
printf("\t");
for (j=;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=;
while(*pos <= 'Z' && *pos >= 'A')
{
cnt++;
pos++;
}
return cnt;
} bool checkMat(EdgeType *p,VertexType numvex)
{
int i,j;
for (i=;i<numvex;i++)
{
for(j=i+;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=;i<(*g).numVexs;i++)
{
(*g).vexs[i]=*v;
v++;
} //init Mat
for (i=;i<(*g).numVexs;i++)
{
for (j=;j<(*g).numVexs;j++)
{
(*g).Mat[i][j] = *(p + MAXVEX*i + j);
}
}
if(checkMat(&((*g).Mat[][]),(*g).numVexs) == false)
{
printf("init error!\n");
getchar();
exit();
}
} void init_path(EdgeType *p,int num)
{
int i,j;
for (i=;i<num;i++)
{
for (j=;j<num;j++)
{
*(p + i*MAXVEX + j) = j;
}
}
} void floyd(MGraph g,EdgeType *des,EdgeType *path)
{
//初始化 des,path
int i,j; for (i=;i<g.numVexs;i++)
{
for (j=;j<g.numVexs;j++)
{
*(des + i*MAXVEX +j) = g.Mat[i][j];
*(path + i*MAXVEX +j) = j;
}
} int k;
for (k=;k<g.numVexs;k++)
{
for (i=;i<g.numVexs;i++)
{
for (j=;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[][]);
prt_maxtix(&grp.Mat[][],grp.numVexs);
printf("Floyd start!\n");
floyd(grp,&edgeDest[][],&edgePath[][]); printf("Dest:\n");
prt_maxtix(&edgeDest[][],grp.numVexs); printf("Edge:\n");
prt_maxtix(&edgePath[][],grp.numVexs); prt_short_path(,,&edgePath[][]);
printf("finish\n");
getchar();
return ;
}

算法学习记录-图——最小路径之Floyd算法的更多相关文章

  1. 算法学习记录-图——最小生成树之prim算法

    一个连通图的生成树是一个极小的连通子图,它包含图中全部的顶点(n个顶点),但只有n-1条边. 最小生成树:构造连通网的最小代价(最小权值)生成树. prim算法在严蔚敏树上有解释,但是都是数学语言,很 ...

  2. 算法学习->求解三角形最小路径及其值

    00 问题 00-1 描述 对给定高度为n的一个整数三角形,找出从顶部到底部的最小路径和.每个整数只能向下移动到与之相邻的整数. 找到一个一样的力扣题:120. 三角形最小路径和 - 力扣(LeetC ...

  3. 算法学习->求解三角形最小路径

    00 问题 00-1 描述 对给定高度为n的一个整数三角形,找出从顶部到底部的最小路径和.每个整数只能向下移动到与之相邻的整数. 找到一个一样的力扣题:120. 三角形最小路径和 - 力扣(LeetC ...

  4. 算法学习记录-图——最短路径之Dijkstra算法

    在网图中,最短路径的概论: 两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点. 维基百科上面的解释: 这个算法是通过为每个顶点 v 保留目前为止所找到的从 ...

  5. 算法学习记录-图——最小生成树之Kruskal算法

    之前的Prim算法是基于顶点查找的算法,而Kruskal则是从边入手. 通俗的讲:就是希望通过 边的权值大小 来寻找最小生成树.(所有的边称为边集合,最小生成树形成的过程中的顶点集合称为W) 选取边集 ...

  6. 算法学习记录-图(DFS BFS)

    图: 目录: 1.概念 2.邻接矩阵(结构,深度/广度优先遍历) 3.邻接表(结构,深度/广度优先遍历) 图的基本概念: 数据元素:顶点 1.有穷非空(必须有顶点) 2.顶点之间为边(可空) 无向图: ...

  7. 算法学习记录-图——应用之关键路径(Critical Path)

    之前我们介绍过,在一个工程中我们关心两个问题: (1)工程是否顺利进行 (2)整个工程最短时间. 之前我们优先关心的是顶点(AOV),同样我们也可以优先关心边(同理有AOE).(Activity On ...

  8. 算法学习记录-图——应用之拓扑排序(Topological Sort)

    这一篇写有向无环图及其它的应用: 清楚概念: 有向无环图(DAG):一个无环的有向图.通俗的讲就是从一个点沿着有向边出发,无论怎么遍历都不会回到出发点上. 有向无环图是描述一项工程或者系统的进行过程的 ...

  9. 图的最短路径---弗洛伊德(Floyd)算法浅析

    算法介绍 和Dijkstra算法一样,Floyd算法也是为了解决寻找给定的加权图中顶点间最短路径的算法.不同的是,Floyd可以用来解决"多源最短路径"的问题. 算法思路 算法需要 ...

随机推荐

  1. SSH之小问题解惑

    (注:以下版本指的是spring3+hibernate3+struts2) 1,web开发中,servlet对象是否线程安全? 当一个http请求到来时,web容器的调度线程(Dispach Thre ...

  2. Linux--NiaoGe-Service-07网络安全与主机基本防护

    Linux系统内自带的防火墙有两层: 第一层:数据包过滤防火墙:IP Filtering和Net Filter 要进入Linux本机的数据包都会先通过Linux预先内置的防火墙(Net Filter) ...

  3. Spark Mllib里如何将数据集按比例随机地分成trainData、testData和validationData数据集(图文详解)

    不多说,直接上干货! 具体详情见 Hadoop+Spark大数据巨量分析与机器学习整合开发实战的第11章 电影推荐引擎

  4. Java基础50题test2—输出素数

    [输出素数] 题目:判断 101-200 之间有多少个素数,并输出所有素数. 程序分析:判断素数的方法:用一个数分别去除 2 到 sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数 pu ...

  5. Symbol.iterator 和 for of

    Symbol.iterator 和 for of 是es6的新特性 可以为对象设置 自己的迭代器 首先介绍我们的for of var arr = [1,2,3,8,33] for (var i of ...

  6. 常用验证函数isset()/empty()/is_numeric()函数

    1) isset()用来检查变量是否设置,若变量存在且值不为NULL时为TRUE: 检查多个变量时变量要全部存在且值不为NULL时为TRUE: 若用函数unset()释放后再用isset()检测时为F ...

  7. linux下phpstudy的搭建以及网站的搭建

    step1: 下载SSH连接到IP地址(阿里云上购买的) step2: 安装下载phpstudywget -c http://lamp.phpstudy.net/phpstudy.bin chmod ...

  8. [原创] SOAP UI 创建SOAP工程进行接口测试

    下载及安装 1. 登录http://www.soapui.org/ 2. 鼠标移动到导航头的Downloads选项 3. 点击SOAP UI 4. 下载页面 新建项目 创建项目 1. 创建项目很简单. ...

  9. SVN几个重要的问题

    本文不是系统地讲解SVN,只是对SVN中一些重要的或者笔者一直混淆的问题做简要归纳. SVN的安装可以参考笔者的另一篇技术随笔<SVN安装使用小结>. 1.既然能够通过SVN得到“每一个版 ...

  10. Linux远程连接及常用指令

    一.远程连接 一般,服务器都是特别庞大的,会把它们用一个独立的小屋进行存放,如果有时候需要对服务器进行一些操作,离得近还好,离的远就会破费一些周折了,所以,这个时候我们就需要用到远程连接软件了.推荐使 ...