【算法导论】每对顶点之间的最短路径算法

        对于一个顶点数为N的有向网路图,我们可以通过前面所提到的单源最短路径算法执行N次来获得每一对顶点间的最短路径。这种方法的时间复杂度为O(N*N*N)。如果网络中有负权值的边,则需要使用前面提到的单源最短路径算法之Bellman—Floyd算法。总之,总可以通过单源最短路径来求得每对顶点间的最短路径。这里我就不再用程序实现上述方法,下面介绍Floyd解决这一问题的另一种算法,它形式简单,利于理解,而且时间复杂度同样为O(N*N*N)。

       Floyd算法是根据给定有向网络的邻接矩阵dist[n][n]来求顶点vi到顶点vj的最短路径。这一算法的基本思想是:假设vi和vj之间存在一条路径,但这并不一定是最短路径,试着在vi和vj之间增加一个中间顶点vk。 若增加vk后的路径(vi, vk, vj) 比(vi, vj)短,则以新的路径代替原路径,并且修改dist[i][j]的值为新路径的权值;若增加vk后的路径比(vi, vj)更长,则维持dist[i][j]不变。然后在修改后的dist矩阵中,另选一个顶点作为中间顶点,重复以上的操作,直到除vi和vj顶点的其余顶点都做过中间顶点为止。下面以具体实例来说明问题:

假设有向网路图如下所示:

设原始的最短路径矩阵为L(1),经过一次循环后得到新的最短矩阵为L(2),依此类推,当得到L(N-1)时,我们就得到了最短的路径矩阵。最短路径矩阵的变化情况如下:

具体程序实现如下:

#include<stdio.h>

#define N 5 //顶点个数
#define MAX 10000

void Floyd(int dist[N][N],int A[N][N],int path[N][N])
{

	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
			for(int k=0;k<N;k++)
			{
				/*if(A[i][j]>(A[i][k]+dist[k][j]))//方法一:计算每一次矩阵
				{
					A[i][j]=(A[i][k]+dist[k][j]);
					path[i][j]=path[k][j];
				}*/
				if(A[i][j]>(A[i][k]+A[k][j]))//方法二:计算2的幂次矩阵
				{
					A[i][j]=(A[i][k]+A[k][j]);
					path[i][j]=path[k][j];
				}
			}
}

void main()
{
	int dist[N][N]={{0,3,8,MAX,-4},//图的邻接矩阵
	                {MAX,0,MAX,1,7},
	                {MAX,4,0,MAX,MAX},
	                {2,MAX,-5,0,MAX},
	                {MAX,MAX,MAX,6,0}};
	int A[N][N];
	int path[N][N]={0};//给出两顶点间的路径
	int pre=0;

	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
		{
			A[i][j]=dist[i][j];
			if(dist[i][j]!=MAX)
				path[i][j]=i+1;
			else
				path[i][j]=0;
		}

	for(int k=0;k<2;k++)//若用方法一,需循环N-3次,若用方法二,需要循环lg(N-1)次
		Floyd(dist,A,path);

	printf("每对顶点间的最短路径矩阵为:\n");
	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
			printf("%d ",A[i][j]);
		printf("\n");
	}
	printf("\n每对顶点的具体最短路径为:\n");

	for(int i=0;i<N;i++)
	{
		for(int j=0;j<N;j++)
		{
			printf("%d: %d ",A[i][j],j+1);
		pre=path[i][j];
		while((pre!=0)&&(pre!=i+1))
		{
			printf("<- %d ",pre);
			pre=path[i][pre-1];
		}
		printf(" <- %d\n",i+1);
		}
	}
}

结果显示如下:

程序不但显示了两点之间的最短路径长度,而且显示了具体的路径。在程序中,我用了两种方法求最短路径矩阵,其中第二种方法更加简单的,因为我们要求的最短路径矩阵为L(N-1)。比如说当N=5时,我们需要最终得到L(4),我们可以只求L(1)、L(2)、L(4),而不需要求得每一个L。


注:如果程序出错,可能是使用的开发平台版本不同,请点击如下链接: 解释说明

原文:http://blog.csdn.net/tengweitw/article/details/17577623

作者:nineheadedbird

时间: 2025-01-18 13:25:21

【算法导论】每对顶点之间的最短路径算法的相关文章

数据结构例程——每对顶点之间的最短路径

本文是[数据结构基础系列(7):图]中第14课时[每对顶点之间的最短路径]的例程. [Floyd算法实现] (程序中graph.h是图存储结构的"算法库"中的头文件,详情请单击链接-) #include <stdio.h> #include <malloc.h> #include "graph.h" #define MaxSize 100 void Ppath(int path[][MAXV],int i,int j) //前向递归查找路径上

[算法系列之二十九]Bellman-Ford最短路径算法

单源最短路径 给定一个图,和一个源顶点src,找到从src到其它所有所有顶点的最短路径,图中可能含有负权值的边. Dijksra的算法是一个贪婪算法,时间复杂度是O(VLogV)(使用最小堆).但是迪杰斯特拉算法在有负权值边的图中不适用,Bellman-Ford适合这样的图.在网络路由中,该算法会被用作距离向量路由算法. Bellman-Ford也比迪杰斯特拉算法更简单和同时也适用于分布式系统.但Bellman-Ford的时间复杂度是O(VE),这要比迪杰斯特拉算法慢.(V为顶点的个数,E为边的

[算法系列之三十]Dijkstra单源最短路径算法

单源最短路径问题 给定一个带权有向图 G=(V,E) ,其中每条边的权是一个非负实数.另外,还给定 V 中的一个顶点,称为源.现在我们要计算从源到所有其他各顶点的最短路径长度.这里的长度是指路上各边权之和.这个问题通常称为单源最短路径问题. 前面Bellman-Ford最短路径算法讲了单源最短路径的Bellman-Ford算法(动态规划算法).这里介绍另外一个更常见的算法Dijkstra算法. Dijkstra算法和 最小生成树Prim算法最小生成树算法非常类似,大家可以先熟悉下个算法.两个算法

算法导论-【急求!】降低算法时间复杂度的方法?附图附代码!多谢!!

问题描述 [急求!]降低算法时间复杂度的方法?附图附代码!多谢!! 第一次来CSDN求教大神们!恳请多多指教!!我在用matlab编写一个小算法,这个算法里面可能多次循环的嵌套,导致得到最终结果(输入Reader=800,Tag=1000,r=30,范围为[1,900]的时候),花费了将近800多秒!!!劳驾各方神圣给我指点迷津,降低我这个算法的时间复杂度,有什么好点子好方法么? 更新:原题是RFID网络冗余阅读器去除算法,即要去除掉系统网络中冗余的阅读器,就是图中的红色圈圈,下图是已经去除后的

【算法导论】排序 (二):堆排序

四.(1)堆排序 第一次听堆排序是在107lab听忠哥讲的,但是没讲怎么实现.那时刚看了数据结 构的二叉树,还以为要通过指针建立二叉树的方式来实现,觉得挺难的. 其实堆排序实现没有想象中 的那么难. "堆"这个词最初是在堆排序中提出来的,但后来就逐渐指"废料收集储存区",就像程 序设计语言Lisp和Java中所提供的设施那样.我们这里的堆数据结构不是废料收集存储区. 堆排序的 运行时间与归并排序一样为O(n lg n),  但是一种原地(in place)排序. (

【算法导论】单源最短路径之Bellman-Ford算法

        单源最短路径指的是从一个顶点到其它顶点的具有最小权值的路径.我们之前提到的广度优先搜索算法就是一种无权图上执行的最短路径算法,即在所有的边都具有单位权值的图的一种算法.单源最短路径算法可以解决图中任意顶点间的最短路径.         对于单源最短路径问题,一般有两种经典解法:1.对于有权值为负的图,采用Bellman-Ford算法:2.对于权值全为正的图,常采用Dijkstra算法.本文介绍Bellman-Ford算法,下一篇介绍Dijkstra算法. Bellman-Ford

基本数据结构(算法导论)与python

Stack, Queue Stack是后进先出, LIFO, 队列为先进先出, FIFO 在python中两者, 都可以简单的用list实现, 进, 用append() 出, Stack用pop(), Queue用pop(0), pop的时候注意判断len(l)  对于优先队列, 要用到前面讲到的堆 链表和多重数组 这些数据结构在python中就没有存在的价值, 用list都能轻松实现 散列表 为了满足实时查询的需求而产生的数据结构, 查询复杂度的期望是O(1), 最差为O(n) 问题描述, 对

单源最短路径算法--Dijkstra算法和Bellman-Ford算法

Dijkstra算法 算法流程: (a) 初始化:用起点v到该顶点w的直接边(弧)初始化最短路径,否则设为∞: (b) 从未求得最短路径的终点中选择路径长度最小的终点u:即求得v到u的最短路径: (c) 修改最短路径:计算u的邻接点的最短路径,若(v,-,u)+(u,w)<(v,-,w),则以(v,-,u,w)代替. (d) 重复(b)-(c),直到求得v到其余所有顶点的最短路径. 特点:总是按照从小到大的顺序求得最短路径. 假设一共有N个节点,出发结点为s,需要一个一维数组prev[N]来记录

Floyd求最短路径算法详解

倘若我们要在计算机上建立一个交通咨询系统则可以采用图的结构来表示实际的交通网络.其实现最基本的功能,求出任意两点间的最短路径, 求最短路径的经典方法有很多种,最常用的便是迪杰斯特拉算法和佛洛依德(Floyd)算法,这篇文章就着重介绍Floyd算法. 求两点之间的最短路径无外乎有两种情况,一种就是从一点直接到另一点,另一种就是从一点经过n个节点后再到另一个节点,比如说要从A到B,则有两种情况就是A直接到B,或者是从A经过N个节点后再到B,所以,我们假设Dis(AB)为节点A到节点B的最短路径的距离