数据结构:点对之间最短距离--Floyd算法

Floyd算法

Floyd算法

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

算法思想

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

  1. 两点之间有边相连,weight(Vi,Vj)即是最小的。
  2. 通过另一点:中介点,两点相连,使weight(Vi,Vk)+weight(Vk,Vj)最小。

Min_Distance(Vi,Vj)=min{weight(Vi,Vj),weight(Vi,Vk)+weight(Vk,Vj)}。正是基于这种背后的逻辑,再加上动态规划的思想,构成了Floyd算法。故当Vk取完所有顶点后,Distance(Vi,Vj)即可达到最小。

题外话:代码本身不重要,算法思想才是精髓。思想极难得到,而有了思想,稍加经验即可写出代码。向思想的开创者致敬!

思想很难,代码却比较简单,直接上代码

代码

类定义

#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算法代码看似很长,其实并不难。代码中很多都是用于准备工作和输出。

完整代码下载:Floyd算法

转载请注明出处,本文地址:http://blog.csdn.net/zhangxiangdavaid/article/details/38366923

若有所帮助,顶一个哦!

专栏目录:

数据结构:点对之间最短距离--Floyd算法

时间: 2024-07-28 14:30:50

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

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法

44. 蛤蟆的数据结构笔记之四十四弗洛伊德Floyd算法 本篇名言:"希望是厄运的忠实的姐妹. --普希金" 我们继续来看下数据结构图中的一个算法,这个算法来自图灵奖得主. 1.  Floyd算法介绍 Floyd算法又称为插点法,是一种用于寻找给定的加权图中多源点之间最短路径的算法.该算法名称以创始人之一.1978年图灵奖获得者.斯坦福大学计算机科学系教授罗伯特·弗洛伊德命名.注意这个可不是心理学的那个弗洛伊德. 是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径

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

#include<stdio.h> #include<stdlib.h> #include<string.h> typedef char VertexType[4]; typedef char InfoPtr; typedef int VRType; #define INFINITY 100000 //定义一个无限大的值 #define MaxSize 50 //最大顶点个数 typedef int PathMatrix[MaxSize][MaxSize][MaxSiz

所有顶点之间的最短路径算法:Floyd算法。

Floyd算法的基本思想是:设集合S的初始状态为空,然后依次向集合S中加入顶点 0,1,...,n-1,每次加入一个顶点,用二维数组d保存各条最短路径的长度,其中d[i][j]存放的是顶点i到顶点j的最短路径的长度. 详细的说明: Floyd算法中最重要的办法为二维数组d[i][j],d[i][j]为从i到j中间只经过S中的顶点的.所有可能的路径中的最短路径的长度.如果从i到j通过S中的节点无法联通,则设置d[i][j]为正无穷.可以称d[i][j]存放的是从i到j的 当前最短路径 的长度.而随

最短路算法 :Bellman-ford算法 &amp; Dijkstra算法 &amp; floyd算法 &amp; SPFA算法 详解

 本人QQ :2319411771   邮箱 : [email protected] 若您发现本文有什么错误,请联系我,我会及时改正的,谢谢您的合作! 本文为原创文章,转载请注明出处 本文链接   :http://www.cnblogs.com/Yan-C/p/3916281.html . 很早就想写一下最短路的总结了,但是一直懒,就没有写,这几天又在看最短路,岁没什么长进,但还是加深了点理解. 于是就想写一个大点的总结,要写一个全的. 在本文中因为邻接表在比赛中不如前向星好写,而且前向星效率并

最短路径Dijkstra算法和Floyd算法整理、

转载自:http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html 最短路径—Dijkstra算法和Floyd算法 Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹

数据结构:单源最短路径--Dijkstra算法

Dijkstra算法 单源最短路径 给定一带权图,图中每条边的权值是非负的,代表着两顶点之间的距离.指定图中的一顶点为源点,找出源点到其它顶点的最短路径和其长度的问题,即是单源最短路径问题. Dijkstra算法 求解单源最短路径问题的常用方法是Dijkstra(迪杰斯特拉)算法.该算法使用的是贪心策略:每次都找出剩余顶点中与源点距离最近的一个顶点. 算法思想 带权图G=<V,E>,令S为已确定了最短路径顶点的集合,则可用V-S表示剩余未确定最短路径顶点的集合.假设V0是源点,则初始 S={V

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

Dijkstra算法 1.定义概览 Dijkstra(迪杰斯特拉)算法是典型的单源最短路径算法,用于计算一个节点到其他所有节点的最短路径.主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法是很有代表性的最短路径算法,在很多专业课程中都作为基本内容有详细的介绍,如数据结构,图论,运筹学等等.注意该算法要求图中不存在负权边. 问题描述:在无向图 G=(V,E) 中,假设每条边 E[i] 的长度为 w[i],找到由顶点 V0 到其余各点的最短路径.(单源最短路径) 2.算法

hiho一下 第二十四周---最短路径&#183;二:Floyd算法

最短路径·二:Floyd算法 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 万圣节的中午,小Hi和小Ho在吃过中饭之后,来到了一个新的鬼屋! 鬼屋中一共有N个地点,分别编号为1..N,这N个地点之间互相有一些道路连通,两个地点之间可能有多条道路连通,但是并不存在一条两端都是同一个地点的道路. 由于没有肚子的压迫,小Hi和小Ho决定好好的逛一逛这个鬼屋,逛着逛着,小Hi产生了这样的问题:鬼屋中任意两个地点之间的最短路径是多少呢? 提示:其实如果你开心的话,完全可以从

Floyd算法思想

Floyd算法是一个经典的动态规划算法.用通俗的语言来描述的话,首先我们的目标是寻找从点i到点j的最短路径.从动态规划的角度看问题,我们需要为这个目标重新做一个诠释(这个诠释正是动态规划最富创造力的精华所在),floyd算法加入了这个概念 Ak(i,j):表示从i到j中途不经过索引比k大的点的最短路径. 这个限制的重要之处在于,它将最短路径的概念做了限制,使得该限制有机会满足迭代关系,这个迭代关系就在于研究:假设Ak(i,j)已知,是否可以借此推导出Ak-1(i,j). 假设我现在要得到Ak(i