一个有向带权图求它的单源最短路径可以使用Dijkstra算法。
单源最短路径是指:从图中的某个顶点出发,到其余各个顶点权值最小的路径。
Dijkstra算法需要用到三个辅助数组:
- dist[max]:记录当前出发点v到其余各个点的最短权值之和(包括自己,为0);
- path[max]:记录当前每个结点在最短权值路径的状态下的前驱结点;
- s[max]:记录当前状态下的每个结点是否被访问过,访问过为1,没访问为0;
(max为图的顶点数)
Dijkstra算法由于要不断地访问顶点之间的边的信息,所以更适合将图用邻接矩阵进行存储。
本文关于Dijkstra算法的思想就不再赘述,主要是分享Dijkstra算法的代码实现。
算法的核心代码:
void Dijkstra(Mgraph G,int v) {
int num = 0;
int min = 0;
int s[MAX];
int dist[MAX];
int path[MAX];
for (int i = 0; i < G.vexnum; i++)
{
dist[i] = G.arc[v][i];
if (dist[i] != INF) path[i] = v;
else path[i] = -1;
}
for (int i = 0; i < G.vexnum; i++)
{
s[i] = 0;
}
s[v] = 1;
num = 1;
//在未访问的结点中更新dist和path数组以及s数组
while (num < G.vexnum)
{
min = FindMinDist(dist, s, G); //寻找最小的权值结点
s[min] = 1;
for (int i = 0; i < G.vexnum; i++)
{
if (s[i] == 0 && (dist[i] > dist[min] + G.arc[min][i]))
{
dist[i] = dist[min] + G.arc[min][i];
path[i] = min;
}
}
num++;
}
//打印输出结果:
for (int i = 0; i < G.vexnum; i++)
{
cout << dist[i] << " ";
}
cout << endl;
for (int i = 0; i < G.vexnum; i++)
{
cout << path[i] << " ";
}
}
完整代码:
#include<iostream>
using namespace std;
#define MAX 9
#define INF 9999
typedef struct Mgraph {
char Vexnum[MAX]; //图的顶点信息
int arc[MAX][MAX];//二维数组存储顶点之间的边的权值信息
int vexnum;//图的顶点数
int edgenum;//图的边数
};
//创建图
void CreatM(Mgraph& G)
{
int i, j, w;
cout << "请输入图的顶点数和边数" << endl;
cin >> G.vexnum >> G.edgenum;
cout << "请输入顶点信息" << endl;
for (int i = 0; i < G.vexnum; i++)
{
cin >> G.Vexnum[i];
}
//初始化二维数组的边的权值为INF
for (int i = 0; i < G.vexnum; i++)
{
for (int j = 0; j < G.vexnum; j++)
{
if(i == j) G.arc[i][j] = 0;
else G.arc[i][j] = INF;
}
}
//更改二维数组中边的权值为输入进来的权值
for (int k = 0; k < G.edgenum; k++)
{
cout << "请输入边(Vi,Vj)的下标i,j和权重w: " << endl;
cin >> i >> j >> w;
G.arc[i][j] = w;
}
}
void MyPrint(Mgraph G) {
cout << "创建的图的邻接矩阵如下所示: " << endl;
for (int i = 0; i < G.vexnum; i++)
{
for (int j = 0; j < G.vexnum; j++)
{
cout << G.arc[i][j] << " ";
}
cout << endl;
}
}
//在dist数组中找s[i] = 0,权值最小的数组下标。
int FindMinDist(int *pdist,int *s, Mgraph G) {
int num = G.vexnum;
int min = INF;
for (int i = 0; i < num; i++)
{
if (pdist[i] < min && s[i] == 0)
{
min = i;
}
}
return min;
}
//算法核心
void Dijkstra(Mgraph G,int v) {
int num = 0;
int min = 0;
int s[MAX];
int dist[MAX];
int path[MAX];
for (int i = 0; i < G.vexnum; i++)
{
dist[i] = G.arc[v][i];
if (dist[i] != INF) path[i] = v;
else path[i] = -1;
}
for (int i = 0; i < G.vexnum; i++)
{
s[i] = 0;
}
s[v] = 1;
num = 1;
while (num < G.vexnum)
{
min = FindMinDist(dist, s, G);
s[min] = 1;
for (int i = 0; i < G.vexnum; i++)
{
if (s[i] == 0 && (dist[i] > dist[min] + G.arc[min][i]))
{
dist[i] = dist[min] + G.arc[min][i];
path[i] = min;
}
}
num++;
}
for (int i = 0; i < G.vexnum; i++)
{
cout << dist[i] << " ";
}
cout << endl;
for (int i = 0; i < G.vexnum; i++)
{
cout << path[i] << " ";
}
}
int main() {
Mgraph G;
CreatM(G);
//MyPrint(G);
Dijkstra(G,0);
return 0;
}
执行结果: