最短路径一般是基于网图来说的(带有权值的连通图),不带权值可以考虑权值为1来计算。

最短路径是指两顶点之间经过的边上权值之和最少的路径,并且我们称路径上的第一个顶点是源点,最后一个顶点是终点。

求解最短路径的两种算法。迪杰斯特拉算法和弗洛伊德算法。

1、迪杰斯特拉(Dijkstra)算法

    用来求某个顶点到其余所有顶点的最短路径

算法介绍

求V0到其余各个顶点的最短路径。

(1)初始化,P={V0},D0(V0到V0的距离)= 0;Di表示V0到Vi顶点的距离,Di = di0,i不等于0,规定如果Vi顶点与V0不直接相连,则Di = 无穷大。

(2)寻找下一个目标顶点,即在Di(i不属于P)中选择一个点j,是Dj最小,则选择的点Vj放到P中,Vj所在的路径是最短路径。

(3)更新Di(i不属于P),Di = min[Di(旧的,更新之前的),Dj + dji ],更新完所有i(不属于P),返回第2步。直达所有顶点存储到P中。

#define MAXVEX 9
#define INFINITY 65535
typedef int Pathmatirx[MAXVEX];
typedef int ShortPathTable[MAXVEX];
void ShortestPaht_Dijkstra(MGraph G, int V0, Pathmatirx *P, ShortPathTable *D)
{
int v,w,k,min;
int final[MAXVEX];  /*final[w]=1表示求得顶点V0至Vw的最短路径*/
for(v=0;v<G.numVertexes; v++)
{
final[v] = 0;
(*D)[v] = G.matirx[V0][v];
(*P)[v] = 0;
}
(*D)[V0] = 0;  /*v0至v0路径为0*/
final[V0] = 1;/*v0至v0不需要求路径*/
/*开始主循环,每次求得V0到某个顶点V的最短路径*/
for(v = 1; v<G.numVertexes; v++)
{
min = INFINITY;  /*初始化最短距离*/
for(w=0; w<G.numVertexes; w++)  /*寻找离V0最近的顶点*/
{
if(!final[w] && (*D)[w]<min)
{
k = w;
min = (*D)[w]; /*w顶点离v0顶点更近*/
}
}
final[k] = 1;   /*将目前找到的最近的顶点置为1*/
for((w = 0; w<G.numVertexes; w++)   /*修正当前最短路径及距离*/
{
/*如果经过V顶点的路径比现在这条路径短的话*/
if(!final[w] && (min + G.matirx[k][w] <(*D)[w])
{
/*说明找到了更短的路径,修改D[w]和P[w]*/
(*D)[w] = min + G.matirx[k][w];  /*修改当前路径长度*/
(*P)[w] = k;
}
}
}
}

 

2、弗洛伊德(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中则包含了最短路径(具体路径)的信息。

#include <stdio.h>
#define MAXVEX 100
typedef int Pathmatirx[MAXVEX][MAXVEX];
typedef int ShorPathTable[MAXVEX][MAXVEX];
/*Floyd算法,求网图G中各顶点v到其余顶点w的最短路径P[v][w]及带权长度D[v][w]*/
void ShortestPath_Floyd(MGraph G, Pathmatirx *P, ShortPathTable *D)
{
int v,w,k;
for(v=0; v<G.numVertexes; ++v)    /*初始化D与P*/
{
for(w=0; w<G.numVertexes; ++w)  /*D[v][w]的值即为对应点间的权值*/
{
(*D)[v][w] = G.matirx[v][w];
(*P)[v][w] = w; /*初始化P*/
}
}
for(k= 0; k<G.numVertexes; ++k)
{
for(v=0; v<G.numVertexes; ++v)
{
for(w=0; w<G.numVertexes; ++w)  /*如果经过下标为k顶点的路径比原两点之间路径更短*/
{
if((*D)[v][w] > (*D)[v][k] + (D)[k][w])
{
(*D)[v][w] = (*D)[v][k] + (*D)[k][w];
(*P)[v][w] = (*P)[v][k];
}
}
}
}
}