如上图,假设我们要算从顶点0到其余顶点的最短路径,答案如下:
0——0 | 0(自己到自己) |
0——1 | 13(0->1) |
0——2 | 8(0->2) |
0——3 | 13(0->2->3) |
0——4 | 19(0->2->3->4) |
0——5 | 21(0->2->3->4->5) |
0——6 | 20(0->1->6) |
该算法其实就是在无权图最短路径的算法基础上加了一点东西。它们的共同点是都需要一个记录路径长度数组dist[]和一个记录来时走过的路的数组path[];不同的是它多了一个收录的数组S[]
接下来在S未收录的顶点里面找到最小距离的那个顶点v;如果顶点v不存在了(所有点都已经收录并且没有再小的路径了)就表示已经完成了这个算法(找到了从源点i到其余点的所有最短路径了)
在做这些算法之前我们要初始化一些东西;
初始化S数组:将我们要算的某源点i收录进去(赋值为1),其余顶点不收录,(赋值为0)
初始化path[](全部弄成-1)
初始化dist[] :
1、源点dist[i]赋值为0(自己到自己的距离为0)
2、源点i到它触手可及的点 j 要赋值;
3、剩下的dist值全为正无穷;
int j;
dist[i]=0;//从i到i的距离为0
S[i]=1;//收录i
for(j=0;j<N;j++)
{
if(a[i][j]>0)
dist[j]=a[i][j];//如果顶点i到j点有边,初始化j的路径
else
dist[j]=MAX;//正无穷
}
做完一系列初始化工作(有点繁琐)再来开始进行核心算法:
int findmin()//找到dist中未收录最小的值
{
int min=MAX,mini=-1,i;
for(i=0;i<N;i++)
{
if(dist[i]<min&&S[i]==0)
{
min=dist[i];
mini=i;
}
}
return mini;
}
while(1)//进入一个循环
{
int v=findmin();//令v等于dist中未收录最小的值
if(v==-1)//V不存在了,结束搜索
break;
S[v]=1;//将v收录
int w;
for(w=0;w<N;w++)
{
if(a[v][w]>0&&S[w]==0)//如果V的邻接点W未收录
if(dist[v]+a[v][w]<dist[w])//如果点v到w距离比dist[w]小,更新它
{
dist[w]=dist[v]+a[v][w];//更新路径长度
path[w]=v;//更新路径
}
}
}
完整测试代码:
#include<stdio.h>
#include<stdlib.h>
#define MAX 10000000 //正无穷
int N;//顶点数
int E;//边数
int a[10][10];//邻接矩阵
int dist[10];//更新路程
int path[10];//更新路径
int S[10];//记录已收录的点
int findmin();//找到dist中未收录最小的值
void Dijkstra(int x);//x为从某点开始
int main()
{
int i,x1,x2,w;
for(i=0;i<110;i++)
path[i]=-1;//初始化路径
scanf("%d%d",&N,&E);
for(i=0;i<E;i++)
{
scanf("%d%d%d",&x1,&x2,&w);
a[x1][x2]=w;//给每条路赋予权重 这里假设权重即路径(大于0)
}
Dijkstra(0);//从顶点0找最短路径
/*printf("从顶点0到其他顶点的路径分别为\n");
for(i=0;i<N;i++)
{
printf("到顶点%d的路径长度:%d\n0",i,dist[i]);
int t=i;
int way[10],cnt=0;
while(path[t]!=-1)
{
way[cnt++]=t;
t=path[t];
}
while(cnt--) printf("->%d",way[cnt]);
printf("\n");
} */
return 0;
}
int findmin()//找到dist中未收录最小的值
{
int min=MAX,mini=-1,i;
for(i=0;i<N;i++)
{
if(dist[i]<min&&S[i]==0)
{
min=dist[i];
mini=i;
}
}
return mini;
}
void Dijkstra(int x)
{
int i;
dist[x]=0;//从x到x的距离为0
S[x]=1;//收录x
for(i=0;i<N;i++)
{
if(a[x][i]>0)
{
dist[i]=a[x][i];//如果顶点0到该点有边,初始化它们的路径
path[i]=x;
}
else
dist[i]=MAX;
}
//以上是初始化,以下为核心算法
while(1)//进入一个循环
{
int v=findmin();//令v等于dist中未收录最小的值
if(v==-1)//V不存在了,结束搜索
break;
S[v]=1;//将v收录
int w;
for(w=0;w<N;w++)
{
if(a[v][w]>0&&S[w]==0)//如果V的邻接点W未收录
if(dist[v]+a[v][w]<dist[w])//如果点v到w距离比dist[w]小,更新它
{
dist[w]=dist[v]+a[v][w];//更新路径长度
path[w]=v;//更新路径
}
}
}
}