- 程序实现
#include <stdio.h>
#define M 65535 //一个无穷大的数,用来表示两个顶点之间没有连线时的权值
#define N 5 //顶点数
//Dijkstra算法函数,求给定源点到其余各顶点的最短路径
void Dijkstra(int c[N][N], int v, int dist[], int prev[])
{
int s[N];//当前顶点i是否被选入S集合
int mindis,dis;
int i, j, u;
//对图进行赋初值
for(i=0; i<N; i++)
{
dist[i] = c[v][i];//dist[i]表示当前从源到顶点i的最短特殊路径长度
s[i] = 0;//当前顶点i没有被选入S集合
if(dist[i] == M)//如果当前从源到顶点i的最短特殊路径长度为无穷大
prev[i] = -1;//那么到达顶点i的最佳路径上的该顶点的上一个点不是v
else
prev[i] = v;//否则,到达顶点i的最佳路径上的该顶点的上一个点是v
}
dist[v] = 0;//源点到源点的距离为0
s[v] = 1; //表示源点放入S集合
//在集合V-S中寻找具有最短路径的顶点
for(i=1; i < N; i++)
{
mindis = M;
u = v;
for (j=0; j < N; j++)
if(s[j]==0 && dist[j]<mindis)//判断j不在S中
{
mindis = dist[j];
u = j;
}
s[u] = 1;//找到一个具有最短路径的顶点,将其放入S集合
//更新最短路径
for(j=0; j < N; j++)
if(s[j]==0 && c[u][j]<M)//判断j不在S中并且u到j有一条路径
{
dis = dist[u] + c[u][j];//将路径更新为经过S集合中所有顶点的路径
// 如果新的路径更短,就替换掉原来的路径
if(dist[j] > dis)
{
dist[j] = dis;
prev[j] = u;
}
}
}
}
// 输出最短路径
void PrintPrev(int prev[],int v0,int vn)
{
int tmp = vn;
int i, j;
int tmpprv[N];//临时存储路径
//初始化数组
for(i=0; i < N; i++)
tmpprv[i] = 0;
//记录到达点下标
tmpprv[0] = vn+1;
//中间点用循环记录
for(i =0, j=1; j < N ;j++)
{
if(prev[tmp]!=-1 && tmp!=0)
{
tmpprv[i] = prev[tmp]+1;
tmp = prev[tmp];
i++;
}
else break;
}
//输出路径,数组逆向输出
for(i=N-1; i >= 0; i--)
{
if(tmpprv[i] != 0)
{ //排除0元素
printf("V%d", tmpprv[i]);
if(i) //不是最后一个输出符号
printf("->");
}
}
printf("->V%d", vn+1);
}
//主函数
int main()
{
char *Vertex[N]={"V1", "V2", "V3", "V4", "V5"}; //有向图的顶点
int c[N][N]=
{//有向图的邻接矩阵,可以表示出顶点与顶点之间的权值,相当于给图赋初值
{0, 10, M, 30, 100},
{M, 0, 50, M, M},
{M, M, 0, M, 10},
{M, M, 20, 0, 60},
{M, M, M, M, 0},
};
int dist[N]; //存放求得的最短特殊路径长度
int prev[N]; //存放到达某一顶点的最佳路径上的该顶点的上一个点
int i;//用来指代当前顶点,i的范围从0到有向图中顶点的个数-1
//求出源点V1到其余各点的最短路径
Dijkstra(c, 0, dist, prev);
printf("最短路径长度为:\t\t");
printf("最短路径为:");
printf("\n");
for(i=0; i < N; i++)
{
printf("%s->%s:%d\t\t", Vertex[0], Vertex[i], dist[i]);//输出最短路径长度
PrintPrev(prev, 0, i);//输出最短路径
printf("\n");
}
return 0;
}
- 实验结果与分析