最短路径一般是基于网图来说的(带有权值的连通图),不带权值可以考虑权值为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]; } } } } }