最短路径:迪杰斯特拉算法与弗洛伊德算法

对网图和非网图,最短路径含义的不同的。非网图的最短路径:两顶点之间经过的边数最少的路径。网图的最短路径:两顶点之间经过的边上权值之和最少的路径。

迪杰斯特拉(Dijkstra)算法

解决了从某个源点到其余各项点的最短路径问题。时间复杂度为O[n2]。若想找到从源点到某一个特定终点的最短路径,这个问题和求源点到其他所有顶点的最短路径一样复杂。
若源点为v0,终点为v8,此算法不是一下子就求出了v0到v8的最短路径,而是一步步求出它们之间顶点的最短路径,过程中都是基于已经求出的最短路径的基础上,求得更远顶点的最短路径,最终得到想要的结果。

在这里插入图片描述
对于此网图:
程序结束之后,final = {1,1,1,1,1,1,1,1},表示所有顶点均完成了最短路径的查找工作。
D = {0,1,4,7,5,8,10,12,16},表示v0到各个顶点的最短路径数
P = {0,0,1,4,2,4,3,6,7},表示v0到各个顶点的最短路径具体走法。如:P[8] = 7,表示v0到v8的最短路径,顶点v8的前驱顶点是v7,再有P[7] = 6,表示v7的前驱是v6,又P[6] = 3,表示v6的前驱路径是v3,以此类推。由此可得,从v0到v8的最短路径为:v0–>v1–>v2–>v4–>v3–>v6–>v7–>v8

//最短路径算法:迪杰斯特拉算法与弗洛伊德算法
//迪杰斯特拉(Dijkstra)算法,求有向网G的v0顶点到其余顶点v的最短路径P[v]及带权长度D[v]
typedef int Pathmatrix[MAXVEX];				//用于存储最短路径下标的数组
typedef int ShortPathTable[MAXVEX];			//用于存储各点最短路径的权值和
//P[v]的值为前驱顶点下标,D[v]表示v0到v的最短路径长度和
void ShortestPath_Dijkstra(MGraph G, int v0, Pathmatrix* P, ShortPathTable* D)
{
	int v, w, k, min;
	int final[MAXVEX];		//final[w] = 1 表示求得顶点v0至vw的最短路径
	for (v = 0; v< G.numVertexes; v++)
	{
		final[v] = 0;
		(*D)[v] = G.arc[v0][v];
		(*P)[v] = 0;
	}
	(*D)[v0] = 0;
	final[v0] = 1;
	for (v = 1; v < G.numVertexes; v++)
	{
		min = INFINITY;
		for (w = 0; w < G.numVertexes; w++)
		{
			if (!final[w] && (*D)[w] < min)
			{
				k = w;
				min = (*D)[w];
			}
		}
		final[k] = 1;
		for (w = 0; w < G.numVertexes; w++)
		{
			if (!final[w] && (min + G.arc[k][w] < (*D)[w]))
			{
				(*D)[w] = min + G.arc[k][w];
				(*P)[w] = k;
			}
		}
	}
}

弗洛伊德(Floyd)算法

一个二重循环初始化加一个三重循环权值修正,就完成了所有顶点到所有顶点的最短路径计算。时间复杂度:O[n3]

初始化D为邻接矩阵,P如图。
在这里插入图片描述
算法运行完毕后,D矩阵每一行(如第0行)是以v0为起点,对应列为终点的最短路径长。P表示其具体最短路径。以v0到v7为例子,P[0][7] = 1,得到要经过顶点v1,取P[1][7] = 2,得到要过顶点v2,取P[2][7] = 4,得到要过顶点v4,取P[4][7] = 3,得到要经过点v3,以此类推。
在这里插入图片描述

//Floyd算法,求网图G中各顶点v到其余顶点w最短路径P[v][w]及带权长度D[v][w]
typedef int Pathmatrix[MAXVEX][MAXVEX];
typedef int ShortPathTable[MAXVEX][MAXVEX];

void ShortestPath_Floyd(MGraph G, Pathmatrix* P, ShortPathTable* D)
{
	int v, w, k;
	for (v = 0; v < G.numVertexes; v++)
	{
		for (w = 0; w < G.numVertexes; w++)
		{
			(*D)[v][w] = G.arc[v][w];
			(*P)[v][w] = w;
		}
	}
	for (k = 0; k < G.numVertexes; k++)
	{
		for (v = 0; v < G.numVertexes; v++)
		{
			for (w = 0; w < G.numVertexes; w++)
			{
				if ((*D)[v][w] > ((*D)[v][k] + (*D)[k][w]))
				{
					(*D)[v][w] = (*D)[v][k] + (*D)[k][w];
					(*P)[v][w] = (*P)[v][k];
				}
			}
		}
	}
}

最短路径的显示代码:

//最短路径的显示代码
for (v = 0; v < G.numVertexes; v++)
{
	for (w = v + 1; w < v < G.numVertexes; w++)
	{
		printf("v%d-v%d weight: %d ", v, w, D[v][w]);
		k = P[v][w];
		printf(" path: %d ", v);
		while (k != w)
		{
			printf(" -> %d ", k);
			k = P[k][w];
		}
		printf(" -> %d\n", w);
	}
	printf("\n");
}
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值