Dijkstra算法是一个求最短路径的算法
作用:求图中一点到图的其他所有点的最短路径,要求路径全为正的,不能有负值
时间复杂度:O(V^2)
空间复杂度:O(V)
算法步骤详解:
a.初始时,S只包含源点,即S={v},v的距离为0。U包含除v外的其他顶点,即:U={其余顶点},若v与U中顶点u有边,则<u,v>正常有权值,若u不是v的出边邻接点,则<u,v>权值为无穷大。
b.从U中选取一个距离v最小的顶点k,把k,加入S中(该选定的距离就是v到k的最短路径长度)。
c.以k为新考虑的中间点,修改U中各顶点的距离;若从源点v到顶点u的距离(经过顶点k)比原来距离(不经过顶点k)短,则修改顶点u的距离值,修改后的距离值的顶点k的距离加上边上的权。
d.重复步骤b,c直到所有的定点都包括在S集合中。
代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MaxSize 20
#define INFINITY 65535
typedef char VertexType;
//定义图 的邻接矩阵表示法结构
typedef struct Graph {
VertexType ver[MaxSize+1];
int edg[MaxSize][MaxSize];
}Graph;
//邻接矩阵法图的生成函数
void CreateGraph( Graph *g )
{
int i = 0;
int j = 0;
int VertexNum;
VertexType Ver;
printf("请输入图的顶点:\n");
while( '\n' != (Ver=getchar()) )
g->ver[i++] = Ver;
g->ver[i] = '\0';
VertexNum = strlen(g->ver);
printf("请输入相应的的邻接矩阵:\n");
for( i=0; i<VertexNum; i++ )
for( j=0; j<VertexNum; j++ )
scanf("%d", &g->edg[i][j]);
}
//打印图的结点标识符和邻接矩阵
void PrintGraph( Graph g )
{
int i, j;
int VertexNum = strlen(g.ver);
printf("图的顶点为:\n");
for( i=0; i<VertexNum; i++ )
printf("%c ", g.ver[i]);
printf("\n");
printf("图的邻接矩阵为:\n");
for( i=0; i<VertexNum; i++ ) {
for( j=0; j<VertexNum; j++ )
printf("%d ", g.edg[i][j]);
printf("\n");
}
}
//求图的顶点数
int CalVerNum( Graph g )
{
return strlen(g.ver);
}
//将不邻接的顶点之间的权值设置为INFINITY
void SetWeight( Graph *g )
{
for( int i=0; i<CalVerNum(*g); i++ )
for( int j=0; j<CalVerNum(*g); j++ )
if( 0 == g->edg[i][j] )
g->edg[i][j] = INFINITY;
}
//Dijkstra求最短路径函数
void Dijkstra( Graph g )
{
int VertexNum = CalVerNum( g );
int j;
int mini;
int index = 0;
int *used = (int *)malloc(sizeof(int)*VertexNum);
int *distance = (int *)malloc(sizeof(int)*VertexNum);
int *parent = (int *)malloc(sizeof(int)*VertexNum);
int *last = (int *)malloc(sizeof(int)*VertexNum);
SetWeight( &g ); //设置权值
for( int i=0; i<VertexNum; i++ ) {
used[i] = 0;
distance[i] = g.edg[0][i]; //初始化为与编号为0的顶点的距离
last[i] = 0;
}
used[0] = 1;
parent[index++] = 0;
int i;
for( i=0; i<VertexNum-1; i++ )
{
j = 0;
mini = INFINITY;
for( int k=0; k<VertexNum; k++ )
if( (0 == used[k]) && (distance[k] < mini) ) {
mini = distance[k];
j = k; //j为刚刚找到的V-U中到源点路径最短的顶点
}
used[j] = 1;
int k;
for( k=0; k<VertexNum; k++ )
if( (0 == used[k]) && (distance[k] > distance[j] + g.edg[j][k]) ) { //由于有顶点新加入U集合,对距离数组distance进行更新,比较原路径长度与以新加入的顶点为中间点的路径长度
distance[k] = distance[j] + g.edg[j][k];
}
parent[index++] = j;
}
printf("%c到%c的最短路径经过顶点依次为:\n", g.ver[0], g.ver[VertexNum-1]);
for( i=0; i<index; i++ )
printf("%c ", g.ver[parent[i]]);
printf("\n");
printf("最短路径长度为: %d\n", mini);
}
int main()
{
Graph g;
CreateGraph( &g );
PrintGraph( g );
Dijkstra( g );
return 0;
}