Dijkstra算法是用来求解从某个源点到其他各顶点的最短路径(单源最短路径)。
下面的Dijkstra算法的讲解都是基于这个有向图,在遇到其他问题可以类比。
算法的基本思想:
把图中的定点分成两组,第一组包括已确定最短路径的顶点,初始时只含有一个源点,记为集合S;第二组包括尚未确定的最短路径的顶点,记为V-S;按最短路径长度递增的顺序逐个把V-S中的顶点加到S中去,直至从v0出发可以到达的所有顶点都包括在S中。
【讲到这里要打断一下:我最初就是不能理解这个“按最短路径长度的递增顺序”(1)这个顺序到底是什么顺序?(2)哪个点到哪个点的最短路径长度?(3)如果是那个已经确定的源点到其他点的最短路径,但是源点并不是到每个点都有路径,在开始给邻接矩阵复制的时候,有的位置是INF,那这个怎么比较????当时心里有无数个问号,找了很多博客,大家都没有详细说明(内心:这个这么好理解?我这么弱?)下面就会一一解答上面的问号。】
接着上面,在这个过程中,总保持v0到第一组S中各顶点的最短路径都不大(小于等于)与v0到第二组V-S的任何顶点的最短路径长度,第二组的顶点对应距离值是从v0到此顶点的只包括第一组S的顶点中为中间顶点的最短路径长度。对于S中任意一点 j,v0到j的路径长度皆小于v0到V-S中任意一点的路径长度。(这也与上面用红色标注的按照最短路径长度的递增顺序)
始点 | 终点 | 最短路径 | 路径长度 |
A | B | (A,C,B) | 19 |
C | (A,C) | 4 | |
D | (A,C,F,D) | 25 | |
E | (A,C,B,E) | 29 | |
F | (A,C,F) | 12 |
该表格表示:A到其余各点的最短路径
看到这里:上述所说的按照对端路径长度的递增顺序逐个把V-S中的顶点加到S中去,但是在拿到一个有向图时,我们怎么可能一眼看出路径长度是多少?需要代码求解。
为了实现该串代码,与要设置需要设置距离向量d[ ](即:源点到该点的最短路径),以及保存路径的向量p[](即:它的前一个点是谁(官方:最短路径上第i个顶点的前驱顶点序号))。
算法的具体步骤可描述如下:
(1)初始化:包括对第一组(集合S:目前集合S只有{v0})的初始化与对距离向量d的初始化(用邻接矩阵中相应的值进行赋值)。
(2)从第二组V-S的顶点中选取一个距离值最小的顶点v加入S,。接着对V-S中的所有顶点值进行修改,修改的方法是,对于V-S中的任意一个顶点k,若图中有边<v,k>,且v0到v的距离加上<v,k>边上的权值之和小于v0到k的距离值,则用“v0到v的距离加上<v,k>边上的权值代替顶点k原来的距离值”,(v作为中间点);反之,则顶点k的距离值保持不变。
。
【我的理解:就是一开始d[k]中肯定就和邻接矩阵中的值一样,有数字,也有INF(即不存在到该点的路径,但是随着S集合中不断加入顶点(按照最短路径的长度递增顺序),源点通过加入的这些顶点就可以到达更多的顶点,每加入一个顶点,就要算一下通过这个刚刚加入的中间点,v0到其他点的距离是否有变短,如果有,则修改相应的值,反之,则保持不变。要保证加入到S中的每个点,源点v0到它们的路径长度是最短的。】
(3)若集合V-S已空,则结束算法。若V-S不为空,则返回步骤(2)。
有向网G采用邻接矩阵存储结构
#include <stdio.h>
#include <stdlib.h>
#define M 20
#define FINITY 50000
typedef struct
{
char vexs[M];
int edges[M][M];
int n,e;
}Mgraph;
创建网络的邻接矩阵算法
void creat(Mgraph *g,int c)
{