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. [Vue] Load components when needed with Vue async components

    In large applications, dividing the application into smaller chunks is often times necessary. In thi ...

  2. 使用Perl合并文件

    使用Perl合并文件 有时需要将整个目录下的小文件合并到一个文件中,以便查阅检索 特性 整个目录完全遍历,自动存入单个文件 顺序遍历文件 待合并的目录 合并后的文件内容 syscfg/test1 sy ...

  3. ZOJ 2476 Total Amount 字符串

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1476 题目大意: 给你n串数字组成的字符串,要求输出他们相加的和. 如:n=  ...

  4. 经验总结56--mybatis返回主键

    使用mybatis框架时,有时候须要新插入的数据的主键是多少. 1.oracle 因为oracle是建的序列文件,获取ID值. <insert id="insert" par ...

  5. div宽度设置width:100%后再设置padding或margin超出父元素的解决办法

    div宽度设置width:100%后再设置padding或margin超出父元素的解决办法 一.总结 一句话总结:直接加上box-sizing:border-box;即可解决上述问题. 1.box-s ...

  6. 在ArcEngine中使用Geoprocessing工具-执行工具

    转自原文在ArcEngine中使用Geoprocessing工具-执行工具 来解析一下Geoprocessor类的Execute方法,他有两种重载,Execute(IGPProcess, ITrack ...

  7. Java验证是否为纯数字

    package rbq.codedemo; import java.util.regex.Pattern; /** * Created by rbq on 2016/12/13. */ public ...

  8. web网站如何实现兼容手机

    web网站如何实现兼容手机 一.总结 一句话总结:加上这句话即可:<meta name="viewport" content="width=device-width ...

  9. 【机器学习实战】第2章 k-近邻算法(kNN)

    第2章 k-近邻算法 KNN 概述 k-近邻(kNN, k-NearestNeighbor)算法主要是用来进行分类的. KNN 场景 电影可以按照题材分类,那么如何区分 动作片 和 爱情片 呢? 动作 ...

  10. 【前端统计图】echarts实现单条折线图

    五分钟上手: 图片.png <!DOCTYPE html> <html> <head> <meta charset="utf-8"> ...