数据结构的最短路径是指在网图中,两个结点之间边上权值之和最小的路径。
Dijkstra算法的理解
和前面的最小生成树还是有类似之处
从原点到终点
那么就以源点V0开始,
定义三个数组
final[MAX] : 是用来判决的 初始化为0
ShortPathTable[MAX] :是用来存储权值之和的(按照数组下标来的)
它每次循环都有更新 是根据当前所在结点位置与后面结点的权值 和上次求的最小路径值之和min所更新
更新部分即:比如我从V0到V8结点。 之间有经过V5结点,min是V0到V5的最小路径,那么后面SPT数组的元素,将更新为与V5相关边的权值+min
Patharc[MAX]: 存储数组下标位置的上一个结点 记录最短路径
#include<iostream>
#include <iomanip>
using namespace std;
typedef char Vertextype;//顶点类型
typedef int Edgetype;//边缘权值
typedef int Status;
#define MAXVER 9//最大顶点数
#define INF 65535//代表无穷
#define NULL 0
//定义Dijktre算法的相关数组
typedef int Patharc[MAXVER];//存储最短路径数组下标
typedef int ShortPathTable[MAXVER];//用于存储路径之间的权值最小和
//定义图——邻接矩阵
typedef struct Graph
{
Vertextype Ver[MAXVER];
Edgetype Arc[MAXVER][MAXVER];
int NumVer, NumEdg;
}MGraph;
//生成图——邻接矩阵
Status CreatGraph(MGraph &G)
{
int i, j, w;
cout << "Please enter the number of verticesof the graph : " << endl;
cin >> G.NumVer;
cout << "Please enter the number of edges the graph : " << endl;
cin >> G.NumEdg;
cout << "Please enter the name of vex : " << endl;
for (i = 0; i < G.NumVer; i++){
//cout << "Please enter the NO." << i + 1 << "%d name of vex : " << endl;
cin >> G.Ver[i];
}
cout << "Diagonal infinity ..." << endl;
for (i = 0; i < G.NumVer; i++)
for (j = 0; j < G.NumVer; j++)
{
G.Arc[i][j] = INF;//简单图 不循环
//cout << G.arc[i][j] << endl;//不理解为啥是1
}
cout << "...Diagonal infinity" << endl;
for (int k = 0; k < G.NumEdg; k++){
//因为具体哪条边存在不一定 所以选择性输入边
cout << "Enter the subscripts and weights from vertex vi to vertex vj : " << endl;
cin >> i >> j >> w;
/*cout << "Please enter the subscript j of the edge : " << endl;
cin >> j;
cout << "Please enter the weight from vertex "<<i<<" to vertex "<<j<<" : " << endl;
cin >> w;*/
G.Arc[i][j] = w;
G.Arc[j][i] = G.Arc[i][j];//无向图 边的信息 是对称的 //有向图的话 无需设置
}
return 0;
}
Status Shortpath_Dijkstra(MGraph &G, int V0, Patharc &P, ShortPathTable &D)
{
int v, w, k, min;
int final[MAXVER];
//初始化过程
//final数组为判决数组 初始化为0 若走过 则改 1 原始位置为1
//Patharc数组记录最小路径的位置 (下标对应 该位置的上一结点)
//ShortPathTable数组 记录两个结点之间最小路径的权值之和 会根据结点所在位置不断更新
for (v = 0; v < G.NumVer; v++)
{
final[v] = 0;
(D)[v] = G.Arc[V0][v];
(P)[v] = 0;
}
(D)[V0] = 0;
final[V0] = 1;
//一个一个的开始找
for (v = 1; v < G.NumVer; v++)
{
min = INF;//找出某结点边的最小权值 初始化为一个最大值
//寻找出某结点边权值的最小个 且包括源点到它的总权值
for (w = 0; w < G.NumVer; w++)
{
if (!final[w] && (D)[w] < min)
{
k = w;
min = (D)[w];
}
}
//当找出了某结点的最小权值之和
final[k] = 1;//标记此结点
for (w = 0; w < G.NumVer; w++)
{
if (!final[w] && min + G.Arc[k][w] < D[w])//判断结点是否走过 和 选择相关边
{
//从某点 找到 该点 最小权值对应结点K 然后将D P 更新 分别保存D为对应w位置值为前min+对应点边值p记录位置
(D)[w] = min + G.Arc[k][w];
(P)[w] = k;
}
}
}
return 0;
}
Status DispPath(Patharc &P, ShortPathTable &D)
{
for (int i = 0; i < MAXVER; i++)
{
cout << P[i] << endl;
}
for (int i = 0; i < MAXVER; i++)
{
cout << D[i] << endl;
}
return 0;
}
int main()
{
MGraph G;
Patharc P;
ShortPathTable D;
CreatGraph(G);
int V = 0;
Shortpath_Dijkstra(G, V, P, D);
DispPath(P,D);
system("pause");
return 0;
}
这里一定要理解Patharc[MAXVER]和ShortPathTable[MAXVER]的含义
前者最终结果是数组下标与源点的距离,点和点之间的距离 要减去包括源点的距离
后者含义类似
手动画一遍可加深理解