迪科斯彻算法(英语:Dijkstra's algorithm)是由荷兰计算机科学家艾兹赫尔·戴克斯特拉(Edsger Wybe Dijkstra)发明的。迪科斯彻算法使用了广度优先搜索算法。算法解决的是有向图中单个源点到其他顶点的最短路径问题。举例来说,如果图中的顶点表示城市,而边上的权重表示著城市间开车行经的距离,该算法可以用来找到两个城市之间的最短路径。
该算法的输入包含了一个有权重的有向图 G,以及G中的一个来源顶点S。我们以V 表示G 中所有顶点的集合。每一个图中的边,都是两个顶点所形成的有序元素对。(u,v) 表示从顶点 u 到 v 有路径相连。我们以E 所有边的集合,而边的权重则由权重函数 w:E →[0, ∞] 定义。因此,w(u,v) 就是从顶点u 到顶点v 的非负权重(weight)。边的权重可以想像成两个顶点之间的距离。任两点间路径的权重,就是该路径上所有边的权重总和。已知有V 中有顶点s 及t,Dijkstra算法可以找到s 到 t 的最低权重路径(例如,最短路径)。这个算法也可以在一个图中,找到从一个顶点s 到任何其他顶点的最短路径。
看上面的一张图,我们模拟这就是现实生活中的几个城市,现在要从0这个城市到3这个城市,可能的线路有0->3,0->1->2->3,0->5->3,0->5->4->3这四条线路可以走。现实生活中,我们总是希望可以尽可能快的到达终点,按照图上的权值,我们可以知道0->5->3这条道路是最短的路径。那么如何知道这条路径是最短的了,这就是Dijkstra可以解决问题的地方了。C代码如下:
#include<stdio.h>
#define MAX 100
#define INT_MAX 100000
typedef struct{
int g[MAX][MAX]; //代表的是图中的每条边
int n; //顶点的个数
int e; //边的条数
}Graph;
void diskstra(Graph * G,int * least,int * path); // diskstra实现的核心代码
void findMinPath(Graph * G,int * least,int * path); //找最短路径与最短路径的值
int main(void){
int i,j;
int least[MAX] = {0}; //保存每个节点在当前已知路径中的最小权值
int path[MAX] = {0}; //路径,得到当前路径的上一个节点
Graph G;
for(i=0;i<6;i++){
for(j=0;j<6;j++){
G.g[i][j] = 0;
}
}
G.n = 6;
G.e = 8;
//人为的构造每条边,并且默认0的顶点为起点
G.g[0][1] = 10;
G.g[0][5] = 20;
G.g[0][3] = 98;
G.g[1][2] = 18;
G.g[2][3] = 34;
G.g[5][4] = 22;
G.g[5][3] = 7;
G.g[4][3] = 13;
diskstra(&G,least,path);
findMinPath(&G,least,path);
return 0;
}
void diskstra(Graph *G,int * least,int * path){
int i,j;
int min,temp;
int visited[MAX] = {0}; //默认都没有被访问
//初始化,默认0为起点
for(i=0;i<G->n;i++){
if(G->g[0][i] > 0 && i!=0){
least[i] = G->g[0][i];
path[i] = 0;
}else{
least[i] = INT_MAX; //不存在线路,就让其最短距离无穷大
path[i] = -1; //把他的前趋设置为-1,代表不存在
}
}
path[0] = 0; //0的前趋为他自己
least[0] = 0; //最短路径为0
visited[0] = 1; //已被访问
for(i=1;i<G->n;i++){
min = INT_MAX;
for(j=0;j<G->n;j++){
if(least[j] < min && visited[j] == 0){
min = least[j]; //把当前顶点到其他节点的最短距离拿出来
temp = j; //获得到其它最短距离的顶点编号
}
}
visited[temp] = 1; //标示这个顶点已经被访问
//扩展边的最短路径
for(j=0;j<G->n;j++){
if(visited[j] == 0 &&G->g[temp][j] !=0 && min+G->g[temp][j] < least[j]){
least[j] = min+G->g[temp][j];
path[j] = temp;
}
}
}
}
void findMinPath(Graph * G,int * least,int * path){
int stack[MAX] = {0}; //定义一个栈来保存最短路径的线路,类似于dfs
int top = -1;
int v = 3;
int total = least[3]; //求的是到3的最短路径
while(v != 0){
stack[++top] = v;
v = path[v];
}
stack[++top] = v;
printf("最短线路为:");
while(top != -1){
printf("%d ",stack[top--]);
}
printf("最短线路的距离为%d",total);
}
上述代码我们为了给图结合起来是硬编码上述图中的值,实际情况中可能比这要复杂一些。