![079b9eb58563cabd7cf9da490b84f65d.png](https://i-blog.csdnimg.cn/blog_migrate/ab948c9f93706516ec87c2dd09134594.jpeg)
返回目录:
Chilan Yu:《数据结构》目录链接zhuanlan.zhihu.com![16500f0d365c95a84f59b2d2bd13ca8c.png](https://i-blog.csdnimg.cn/blog_migrate/6b6748bbd361c2fc1d9a96961593ccd7.jpeg)
迪杰斯特拉算法只能求出从源点到其他顶点的最短路径,欲求任意一对顶点间的最短路径,可以将每一顶点作为源点,重复调用迪杰斯特拉算法n次,其时间复杂度为
下面介绍一种形式更简单的方法,即佛罗伊德算法,其时间复杂度也是
2. 求任意一对顶点间的最短路径
例7.5:利用佛罗伊德算法,求图7.27(a)所示的带权有向图中G6的每一对顶点之间的最短路径P及其长度D。7.27(c)给出了G6的每一对顶点之间的最短路径P及其路径长度D。
![a7037d10fd5079121d7c31cafceca734.png](https://i-blog.csdnimg.cn/blog_migrate/b9b33e44ef8cbc4b311a630482f82a3c.jpeg)
【算法思想】
设图g用邻接矩阵法表示,求图g中任意一对顶点vi、vj间的的最短路径。(注:以下序号是与图7.27中D、P的上标序号对应的)。
(-1)将vi到vj 的最短的路径长度初始化为
(0)在vi、vj间加入顶点v0,比较(vi,v0,vj)和(vi,vj)的路径的长度,取其中较短的路径作为vi到vj 的且中间顶点号不大于0的最短路径。
(1)在vi、vj间加入顶点v1,得(vi,…, v1)和(v1,…, vj),其中(vi,…,v1)是vi到v1 的且中间顶点号不大于0的最短路径,(v1,…,vj) 是v1到vj 的且中间顶点号不大于0的最……短路径,这两条路径在上一步中已求出。将(vi,…,v1,…,vj)与上一步已求出的且vi到vj 中间顶点号不大于0的最短路径比较,取其中较短的路径作为vi到vj 的且中间顶点号不大于1的最短路径。
(2)在vi、vj间加入顶点v2,得(vi,…,v2)和(v2,…,vj),其中(vi,…,v2)是vi到v2 的且中间顶点号不大于1的最短路径,(v2,…,vj) 是v2到vj 的且中间顶点号不大于1的最短路径,这两条路径在上一步中已求出。将(vi,…,v2,…,vj)与上一步已求出的且vi到vj 中间顶点号不大于1的最短路径比较,取其中较短的路径作为vi到vj 的且中间顶点号不大于2的最短路径。
………
依次类推,经过n次比较和修正,在第(n-1)步,将求得vi到vj 的且中间顶点号不大于n-1的最短路径,这必是从vi到vj的最短路径。
图g中所有顶点偶对vi、vj间的最短路径长度对应一个n阶方阵D。在上述n+1步中,D的值不断变化,对应一个n阶方阵序列。
定义:
n阶方阵序列:D-1, D0, D1, D2, …Dn-1
其中 :
显然,Dn-1中为所有顶点偶对vi、vj间的最终最短路径长度。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
#define MAX_VERTEX_NUM 20//最多顶点个数
#define INFINITY 32768//表示极大值
#define ElemType int
typedef struct Graph{
int arcs[MAX_VERTEX_NUM][MAX_VERTEX_NUM];//二维数组存储邻接矩阵
int vexnum;//顶点数
}Graph;
/*矩阵建图/网*/
//图:0表示没有边,1表示有边
//网:0表示没有边,非0表示边上权值
void CreateMatrix(Graph * G){//一般从下标0开始存图
cout << "请输入矩阵:" << endl;
int x;
for(int i=0;i<G->vexnum;++i){
G->visited[i] = 0;
for(int j=0;j<G->vexnum;++j){
cin >> x;
if(x) G->arcs[i][j] = x;
else G->arcs[i][j] = INFINITY;
if(i==j) G->arcs[i][j] = 0;
}
}
}
typedef struct{
ElemType elem[MAX_VERTEX_NUM];//线性表占用的数组空间
int last;//记录线性表中最后一个元素在数组elem[]中的位置(下标值),空表置为-1
}SeqList;
void AddTail(SeqList *L,ElemType e){//在顺序表末尾插入一个元素e
L->last++;
L->elem[L->last] = e;
}
void InitList(SeqList * L){
L->last = -1;
}
SeqList JoinList(SeqList L1,SeqList L2){
for(int i=0;i<=L2.last;++i)
L1.elem[++L1.last] = L2.elem[i];
return L1;
}
void Floyd(Graph G,int dist[MAX_VERTEX_NUM][MAX_VERTEX_NUM],SeqList path[MAX_VERTEX_NUM][MAX_VERTEX_NUM]){
//path[i][j]为vi到vj的当前最短路径
//dist[i][j]为vi到vj的当前最短路径长度
for(int i=0;i<G.vexnum;++i){//初始化dist[i][j]和path[i][j]
for(int j=0;j<G.vexnum;++j){
InitList(&path[i][j]);
dist[i][j] = G.arcs[i][j];
if(dist[i][j]<INFINITY){
AddTail(&path[i][j],i);
AddTail(&path[i][j],j);
}
}
}
for(int k=0;k<G.vexnum;++k){
for(int i=0;i<G.vexnum;++i){
for(int j=0;j<G.vexnum;++j){
if(dist[i][k]+dist[k][j]<dist[i][j]){
dist[i][j] = dist[i][k]+dist[k][j];
path[i][j] = JoinList(path[i][k],path[k][j]);
}
}
}
}
}
int main()
{
Graph G;
SeqList path[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
int dist[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
cout << "请输入顶点数:";
cin >> G.vexnum;
CreateMatrix(&G);
Floyd(G,dist,path);
for(int i=0;i<G.vexnum;++i){
for(int j=0;j<G.vexnum;++j){
cout << "从" << i << "到" << j << ":";
for(int k=0;k<=path[i][j].last;++k)
cout << path[i][j].elem[k] << " ";
cout << endl;
if(dist[i][j]==INFINITY) cout << -1 << endl;
else cout << "其最短路径长度为" << dist[i][j] << endl;
}
}
return 0;
}
![8586bd99a6bcd30579272fb9c1e75f60.png](https://i-blog.csdnimg.cn/blog_migrate/bb71f26e0e9d0f5df1e14c203e7031b2.jpeg)
返回目录:
Chilan Yu:《数据结构》目录链接zhuanlan.zhihu.com![16500f0d365c95a84f59b2d2bd13ca8c.png](https://i-blog.csdnimg.cn/blog_migrate/6b6748bbd361c2fc1d9a96961593ccd7.jpeg)