数据结构——图的最短路径之迪杰斯特拉Dijkstra算法的理解和实现

数据结构的最短路径是指在网图中,两个结点之间边上权值之和最小的路径。

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]的含义
前者最终结果是数组下标与源点的距离,点和点之间的距离 要减去包括源点的距离
后者含义类似
手动画一遍可加深理解

猜你喜欢

转载自blog.csdn.net/weixin_46096297/article/details/113697887