Dijstra算法是一种用于解决带权图中单源最短路径问题的贪心算法,也就是说,给定一个图和一个源节点,该算法会找到从源节点到图中所有其它节点的最短路径
以下是Dijkstra算法的计本步骤
1.初始化
创建一个距离数组dlist[],其中dlist[i]表示从源节点到节点i的当前已知最短距离,
开始是,将所有距离设置为无穷大,除了源节点,其距离设置为0
创建一个已访问节点的集合,开始时该集合为空
2.迭代
在所有未访问的节点中,选择距离最小的节点u(即dilist[u]的值最小)
将节点u添加到已访问节点的集合中。对于与节点相邻的每个节点v,检查是否可以通过u找到一个更短的路径到v1,换句话说,如果dlist[u]+weight(u,v)(即从源节点到u的距离加上从u到v的边的权重)小于dlist[v],则更新dlist[v]的值为dlist[u]+weight(u,v);重复上述步骤,直到所有节点都被访问过
3.结果
当算法完成时,dlist[]数组将包括从源节点到图中所有其它节点的最短路径
需要注意的是,Dijkstra算法不能用于包含负权边的图,因为负权边可能会导致算法给出错误的结果
#include<stdio.h>
#include<stdlib.h>
#define MAXV 100//定义图中最多能有的顶点数量
#define INF 1000//定义无穷大值,用于表示两个顶点之间没有直接的边
typedef struct
{
int edgs[MAXV][MAXV];//邻接矩阵,存储边的权重
int n, e;//顶点的数量和边的数量
}MatGraph;//定义图的结构体
//一般会写一个函数DisPath用于打印路径,这里写在Dijkstra里
void Create(MatGraph *G)//创建一个图
{
int i, j, w;
//读取顶点数量和边的数量
scanf("%d %d", &G->n, &G->e);
//初始化邻接矩阵,所有边都设置为无穷大
for (i = 0; i < G->n; i++)
{
for ( j = 0; j < G->n; j++)
{
G->edgs[i][j] = INF;
}
}
//读取每一条边的起点。终点和权重,并更新邻接矩阵
for (int p= 0; p < G->e; p++)
{
scanf("%d %d %d", &i, &j, &w);
G->edgs[i][j] = w;//注意:在无向图中,你可能还需设置G->edgs[j][i]=w;
}
}
//使用Dijkstra算法计算从顶点v到所有其它顶点的最短路径
void Dijkstra(MatGraph* G, int v)//v指的是起点
{
int visited[MAXV];//标记顶点是否已被访问
int path[MAXV];//存储最短路径的前一个顶点
int dist[MAXV];//存储从起点到每个顶点的最短路径
int u, Max;
//初始化距离和路径数组
for (int i = 0; i < G->n; i++)
{
dist[i] = G->edgs[v][i];
visited[i] = 0;
if (G->edgs[v][i] != INF)
{
path[i] = v;
}
else
{
path[i] = -1;//初始化为-1,表示没有路径
}
}
//将起点标记为已访问,并将其距离设置为0,但在此代码中已经设置为起点到自身的权重
visited[v] = 1;
//遍历n-1遍,每次找到未访问的顶点中距离最短的顶点
for (int i = 0; i < G->n - 1; i++)
{
Max = INF;
for (int j = 0; j < G->n; j++)
{
if (visited[j] == 0 && dist[j] < Max)
{
Max = dist[j];
u = j;
}
}
visited[u] = 1;//将找到的点标记为已访问
for (int j = 0; j < G->n; j++)
{//更新从起点到所有未访问顶点的距离
if (visited[j] == 0&& dist[j] >G->edgs[u][j] + dist[u])
{
dist[j] = G->edgs[u][j] + dist[u];
path[j] = u;//更新最短路径的前一个顶点
}
}
}
//打印从起点到每个可达顶点的最短距离和路径
int d = 0;
int k = 0;
int apath[MAXV];
for (int i = 0; i < G->n; i++)
{
if (visited[i]==1&&i!=v)
{
printf("%d到顶点%d的距离为%d\t路径如下:",v ,i, dist[i]);
d = 0; apath[d] = 0;
k = i;
while (k != v)
{
apath[++d] = k;
k = path[k];
}
printf("%d", v);
for (int j = d; j >= 1; j--)
{
printf(",%d", apath[j]);
}
printf("\n");
}//说明是被选过的,如果是自
}
}
int main()
{
MatGraph G;
Create(&G);
Dijkstra(&G, 0);
return 0;
}
下面是运行结果,这里有一个孤立点.