Floyd算法

Floyd算法

Dijkstra算法是用于解决单源最短路径问题的,Floyd算法则是解决点对之间最短路径问题的。Floyd算法的设计策略是动态规划,而Dijkstra採取的是贪心策略。当然,贪心算法就是动态规划的特例。

算法思想

点对之间的最短路径仅仅会有两种情况:

  1. 两点之间有边相连。weight(Vi,Vj)即是最小的。

  2. 通过还有一点:中介点,两点相连,使weight(Vi,Vv)+weight(Vv,Vj)最小。

Min_Distance(Vi,Vj)=min{weight(Vi,Vj),weight(Vi,Vv)+weight(Vv,Vj)}。正是基于这样的背后的逻辑。再加上动态规划的思想,构成了Floyd算法。

故当Vv取全然部顶点后,Distance(Vi,Vj)就可以达到最小。Floyd算法的起点就是图的邻接矩阵


题外话:代码本身不重要。算法思想才是精髓。

思想极难得到,而有了思想,稍加经验就可以写出代码。向思想的开创者致敬。


思想非常难。代码却比較简单。直接上代码

代码

类定义
#include<iostream>
#include<iomanip>
#include<stack>
using namespace std;
#define MAXWEIGHT 100
#undef INFINITY
#define INFINITY 1000
class Graph
{
private:
//顶点数
int numV;
//边数
int numE;
//邻接矩阵
int **matrix;
public:
Graph(int numV);
//建图
void createGraph(int numE);
//析构方法
~Graph();
//Floyd算法
void Floyd();
//打印邻接矩阵
void printAdjacentMatrix();
//检查输入
bool check(int, int, int);
};

类实现

//构造函数,指定顶点数目
Graph::Graph(int numV)
{
//对输入的顶点数进行检測
while (numV <= 0)
{
cout << "顶点数有误! 又一次输入 ";
cin >> numV;
}
this->numV = numV;
//构建邻接矩阵。并初始化
matrix = new int*[numV];
int i, j;
for (i = 0; i < numV; i++)
matrix[i] = new int[numV];
for (i = 0; i < numV; i++)
for (j = 0; j < numV; j++)
{
if (i == j)
matrix[i][i] = 0;
else
matrix[i][j] = INFINITY;
}
}
void Graph::createGraph(int numE)
{
/*
对输入的边数做检測
一个numV个顶点的有向图,最多有numV*(numV - 1)条边
*/
while (numE < 0 || numE > numV*(numV - 1))
{
cout << "边数有问题!又一次输入 ";
cin >> numE;
}
this->numE = numE;
int tail, head, weight, i;
i = 0;
cout << "输入每条边的起点(弧尾)、终点(弧头)和权值" << endl;
while (i < numE)
{
cin >> tail >> head >> weight;
while (!check(tail, head, weight))
{
cout << "输入的边不对!请又一次输入 " << endl;
cin >> tail >> head >> weight;
}
matrix[tail][head] = weight;
i++;
}
}
Graph::~Graph()
{
int i;
for (i = 0; i < numV; i++)
delete[] matrix[i];
delete[]matrix;
}
/*
弗洛伊德算法
求各顶点对之间的最短距离
及其路径
*/
void Graph::Floyd()
{
//为了不改动邻接矩阵,多用一个二维数组
int **Distance = new int*[numV];
int i, j;
for (i = 0; i < numV; i++)
Distance[i] = new int[numV];
//初始化
for (i = 0; i < numV; i++)
for (j = 0; j < numV; j++)
Distance[i][j] = matrix[i][j]; //prev数组
int **prev = new int*[numV];
for (i = 0; i < numV; i++)
prev[i] = new int[numV];
//初始化prev
for (i = 0; i < numV; i++)
for (j = 0; j < numV; j++)
{
if (matrix[i][j] == INFINITY)
prev[i][j] = -1;
else
prev[i][j] = i;
} int d, v;
for (v = 0; v < numV; v++)
for (i = 0; i < numV; i++)
for (j = 0; j < numV; j++)
{
d = Distance[i][v] + Distance[v][j];
if (d < Distance[i][j])
{
Distance[i][j] = d;
prev[i][j] = v;
}
}
//打印Distance和prev数组
cout << "Distance..." << endl;
for (i = 0; i < numV; i++)
{
for (j = 0; j < numV; j++)
cout << setw(3) << Distance[i][j];
cout << endl;
}
cout << endl << "prev..." << endl;
for (i = 0; i < numV; i++)
{
for (j = 0; j < numV; j++)
cout << setw(3) << prev[i][j];
cout << endl;
}
cout << endl;
//打印顶点对最短路径
stack<int> s;
for (i = 0; i < numV; i++)
{
for (j = 0; j < numV; j++)
{
if (Distance[i][j] == 0);
else if (Distance[i][j] == INFINITY)
cout << "顶点 " << i << " 到顶点 " << j << " 无路径! " << endl;
else
{
s.push(j);
v = j;
do{
v = prev[i][v];
s.push(v);
} while (v != i);
//打印路径
cout << "顶点 " << i << " 到顶点 " << j << " 的最短路径长度是 "
<< Distance[i][j] << " ,其路径序列是...";
while (!s.empty())
{
cout << setw(3) << s.top();
s.pop();
}
cout << endl;
}
}
cout << endl;
}
//释放空间
for (i = 0; i < numV; i++)
{
delete[] Distance[i];
delete[] prev[i];
}
delete[]Distance;
delete[]prev;
}
//打印邻接矩阵
void Graph::printAdjacentMatrix()
{
int i, j;
cout.setf(ios::left);
cout << setw(7) << " ";
for (i = 0; i < numV; i++)
cout << setw(7) << i;
cout << endl;
for (i = 0; i < numV; i++)
{
cout << setw(7) << i;
for (j = 0; j < numV; j++)
cout << setw(7) << matrix[i][j];
cout << endl;
}
}
bool Graph::check(int tail, int head, int weight)
{
if (tail < 0 || tail >= numV || head < 0 || head >= numV
|| weight <= 0 || weight >= MAXWEIGHT)
return false;
return true;
}

主函数

int main()
{
cout << "******Floyd***by David***" << endl;
int numV, numE;
cout << "建图..." << endl;
cout << "输入顶点数 ";
cin >> numV;
Graph graph(numV);
cout << "输入边数 ";
cin >> numE;
graph.createGraph(numE);
cout << endl << "Floyd..." << endl;
graph.Floyd();
system("pause");
return 0;
}

执行






小结

Floyd算法代码看似非常长,事实上并不难。代码中非常多都是用于准备工作和输出。关键代码就是三层for循环。


完整代码下载:Floyd算法




若有所帮助,顶一个哦。


专栏文件夹:

版权声明:本文博主原创文章。转载,转载请注明出处。

数据结构:点之间的最短距离--Floyd算法的更多相关文章

  1. 深度解析(一六)Floyd算法

    Floyd算法(一)之 C语言详解 本章介绍弗洛伊德算法.和以往一样,本文会先对弗洛伊德算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 弗洛伊德 ...

  2. 【Aizu - 0189】Convenient Location (最短路 Floyd算法)

    Convenient Location 直接翻译了 Descriptions 明年毕业的A为就业而搬家.就职的公司在若干城市都有办公室,不同天出勤的办公室也不同.所以A在考虑住在哪去各个办公室的时长最 ...

  3. 数据结构与算法——弗洛伊德(Floyd)算法

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

  4. _DataStructure_C_Impl:Floyd算法求有向网N的各顶点v和w之间的最短路径

    #include<stdio.h> #include<stdlib.h> #include<string.h> typedef char VertexType[4] ...

  5. Floyd算法——计算图中任意两点之间的最短路径

    百度百科定义:传送门 一.floyd算法 说实话这个算法是用来求多源最短路径的算法. 算法原理: 1,从任意一条单边路径开始.所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大. 2,对 ...

  6. 数据结构与算法--最短路径之Floyd算法

    数据结构与算法--最短路径之Floyd算法 我们知道Dijkstra算法只能解决单源最短路径问题,且要求边上的权重都是非负的.有没有办法解决任意起点到任意顶点的最短路径问题呢?如果用Dijkstra算 ...

  7. 最短路径—Dijkstra算法和Floyd算法

    原文链接:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最后边附有我根据文中Dijkstra算法的描述使用jav ...

  8. floyd算法小结

    floyd算法是被大家熟知的最短路算法之一,利用动态规划的思想,f[i][j]记录i到j之间的最短距离,时间复杂度为O(n^3),虽然时间复杂度较高,但是由于可以处理其他相似的问题,有着广泛的应用,这 ...

  9. Floyd算法(三)之 Java详解

    前面分别通过C和C++实现了弗洛伊德算法,本文介绍弗洛伊德算法的Java实现. 目录 1. 弗洛伊德算法介绍 2. 弗洛伊德算法图解 3. 弗洛伊德算法的代码说明 4. 弗洛伊德算法的源码 转载请注明 ...

随机推荐

  1. 折腾了我两天的springboot数据源datasource循环依赖问题,都被搞疯掉了

    在做项目重构的时候增加了两个功能 1.多数据源. 2.token的验证从以前的数据库验证,移到了redis端. 1.多数据源使用 druid-spring-boot-starter 套件 其核心代码如 ...

  2. eclipse启动tomcat报错

    错误信息:   严重: A child container failed during start java.util.concurrent.ExecutionException: org.apach ...

  3. [Nuxt] Build a Navigation Component in Vue.js and Use in a Nuxt Layout

    You can isolate parts of templates you want to re-use into components, but you can also reuse those ...

  4. AM335x(TQ335x)学习笔记——Nand&amp;&amp;网卡驱动移植

    移植完毕声卡驱动之后本想再接再励,移植网卡驱动,但没想到的是TI维护的内核太健壮,移植网卡驱动跟之前移植按键驱动一样简单,Nand驱动也是如此,于是,本人将Nand和网卡放在同一篇文章中介绍.介绍之前 ...

  5. SQLITE3 使用总结(直接使用C函数)

    转载网址:http://blog.chinaunix.net/uid-8447633-id-3321394.html 前序: Sqlite3 的确很好用.小巧.速度快.但是因为非微软的产品,帮助文档总 ...

  6. 结合Wireshark捕获分组深入理解TCP/IP协议栈之DNS协议

    摘要:     本文简单介绍了DNS协议理论知识,给出URL解析步骤,详细讲述了DNS报文各个字段含义,并从Wireshark俘获分组中选取DNS相关报文进行分析. 一.概述 1.1 DNS      ...

  7. IE9下不显示select

    由于IE8和IE9下不兼容,需要在头部加入: <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7&q ...

  8. idea+springboot+freemarker热部署(转)

    今天在学习springboot集成freemarker模板引擎修改代码时,发现每次修改一次freemarker文件时,都必须重启下应用,浏览器刷新才能显示修改后的内容,这样效率太低,每次启动一次应用都 ...

  9. Ubuntu UEFI 模式下安装基本原则

    https://help.ubuntu.com/community/UEFI Introduction The Extensible Firmware Interface (EFI) or its v ...

  10. spring getbean 方法分析(很实用!)

    十年阿里,就只剩下这套Java开发体系了 >>>   在最近的项目中,有个地方我们不得不实用getBean的方法,自己从Spring context中获取bean进行数据库操作. 方 ...