弗洛伊德(Floyd)算法 主要是用于计算图中所有顶点对之间的最短距离长度的算法,如果是要求某一个特定点到图中所有顶点之间的最短距离可以用Dijkstra(迪杰斯特拉)算法来求。
弗洛伊德(Floyd)算法的算法过程是:
1、从任意一条单边路径开始。所有两点之间的距离是边的权,如果两点之间没有边相连,则权为无穷大。
2、对于每一对顶点 u 和 v,看看是否存在一个顶点 w 使得从 u 到 w 再到 v 比已知的路径更短。如果是更新它。
把图用邻接矩阵G表示出来,如果从Vi到Vj有路可达,则G[i,j]=d,d表示该路的长度;否则G[i,j]=无穷大。定义一个矩阵D用来记录所插入点的信息,D[i,j]表示从Vi到Vj需要经过的点,初始化D[i,j]=j。把各个顶点插入图中,比较插点后的距离与原来的距离,G[i,j] = min( G[i,j], G[i,k]+G[k,j] ),如果G[i,j]的值变小,则D[i,j]=k。在G中包含有两点之间最短道路的信息,而在D中则包含了最短路径的信息。
比如,要寻找从V5到V1的路径。根据D,假如D(5,1)=3则说明从V5到V1经过V3,路径为{V5,V3,V1},如果D(5,3)=3,说明V5与V3直接相连,如果D(3,1)=1,说明V3与V1直接相连。
时间复杂度和空间复杂度
时间复杂度:O(n^3);
空间复杂度: O(n^2);
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConAppFlody
{
class Program
{
private const int MaxSize = 6;
private const int INF = 32767; //INF表示∞
private const int MAXV = 4; //最大顶点个数
//结构体的成员定义里不能直接赋值,也就是等号后的应该移除,在你后面实例化整个结构体以后,
//再对Study_Data[n].input=new double[50] 其他成员类似。顺便说下其实用class简单得多。
struct VertexType
{
public int no; //顶点编号
public int info; //顶点其他信息
} ; //顶点类型
struct MGraph //图的定义
{
public int[,] edges; //邻接矩阵
public int n, e; //顶点数,弧数
public VertexType[] vexs; //存放顶点信息
} ; //图的邻接矩阵类型
static void initdata()
{
int i,j;
MGraph g;
g.n = MAXV; g.e = 8;
g.edges = new int[MAXV, MAXV];
g.vexs = new VertexType[MAXV];
//int [,] anArray = new int [2, 4] {{1,2,3,4},{5,6,7,8}};
int[,] a = new int[MAXV, MAXV] {
{0, 5,INF,7},
{5, 0, 4,1},
{INF, 4, 0,INF},
{7,1,INF,0}
};
for (i = 0; i < g.n; i++) //建立图的图的邻接矩阵
for (j = 0; j < g.n; j++)
g.edges[i, j] = a[i, j];///////////////////////////////////////////////
Console.WriteLine("各顶点的最短路径:");
Floyd(g);
}
static void Floyd(MGraph g)
{
int[,] A = new int[MAXV, MAXV];//A用于存放当前顶点之间的最短路径长度,分量A[i][j]表示当前顶点vi到顶点vj的最短路径长度。
int[,] path = new int[MAXV, MAXV];//从顶点vi到顶点vj的路径上所经过的顶点编号不大于k的最短路径长度。
int i, j, k;
for (i = 0; i < g.n; i++)
{
for (j = 0; j < g.n; j++)//对各个节点初始已经知道的路径和距离
{
A[i, j] = g.edges[i, j];
path[i, j] = -1;
}
}
for (k = 0; k < g.n; k++)
{
for (i = 0; i < g.n; i++)
for (j = 0; j < g.n; j++)
if (A[i, j] > A[i, k] + A[k, j])//从i到j的路径比从i经过k到j的路径长
{
A[i, j] = A[i, k] + A[k, j];//更改路径长度
path[i, j] = k;//更改路径信息经过k
}
}
Dispath(A, path, g.n); //输出最短路径
}
static void Dispath(int[,] A, int[,] path, int n)
{
int i, j;
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
{
if (A[i, j] == INF)
{
if (i != j)
{
Console.WriteLine("从{0}到{1}没有路径\n", i, j);
}
}
else
{
Console.Write("从{0}到{1}=>路径长度:{2} 路径:", i, j, A[i, j]);
Console.Write("{0},", i); //输出路径上的起点
Ppath(path,i,j); //输出路径上的中间点
Console.WriteLine("{0}", j); //输出路径上的终点
}
}
}
static void Ppath(int[,] path, int i, int j) //前向递归查找路径上的顶点
{
int k;
k = path[i, j];
if (k == -1) return; //找到了起点则返回
Ppath(path, i, k); //找顶点i的前一个顶点k
Console.Write("{0},", k); //输出路径上的终点
Ppath(path, k, j); //找顶点k的前一个顶点j
}
static void Main(string[] args)
{
initdata();
//Console.Write("{0}", MaxSize);
//Console.Write("{0}", MAXV);
Console.ReadKey();
}
}
}