数据结构之图论算法(五)——关键路径(Dijkstra算法与Floyd算法)

最短路径

1.最短路径问题

一般是求带权有向图G = (V,E)中的一个或多个点到G中其他各个点的最短路径。

源点:路径上的第一个顶点
终点:最后一个顶点

求解方法:

  • 单源点最短路径——迪杰斯特拉(Dijkstra)算法
  • 多源点最短路径——佛洛伊德(Floyd)算法

2.Dijkstra算法

——从一个指定给源点到图上其余各点的最短路径

【思路】按路径长度递增的次序产生最短路径

  • 引进一个辅助向量D,每个分量D[i]表示当前所找到的起始点v到每个终点vi的最短路径的长度。

  • (类比于最小生成树中的closedge数组的使用每次纳入一个点都更新一次数组,只不过closedge是整个连通分量到其他顶点最短距离,现在是起点V₀到其他各个顶点的最短距离)

  1. 初始状态:D[ 0 ] = arcs[ v ][ vi ],S = { v }
  2. 选取当前最短路径:D[ j ] = Min { D[ i ] | vi ∈ V-S},vj就是当前求得的一条从v0出发的最短路径的终点,令S = S U { vj }
  3. 更新从v到V-S上任一顶点vk的当前最短路径长度: D[ k ] = Min { D[ k ],D[ j ] + arcs[ vj ][ vk ] }
  4. 重复执行2、3共n-1次
算法满足最优子结构原则

图示如下:
在这里插入图片描述

该思想可以表示成下列伪代码:

	清除所有点的标号			//这些点的标号使用来表示两点间的距离是否已经算过,
							//如果标记了就说明算过了,没有标记就要重新计算
							//这样一来可以避免重复计算,提高效率
	设d[0] = 0,其他d[i] = INF;
	循环n次{
		在所有未标号结点中,选出d值最小的结点x;
		给结点x标记;
		对于从x出发的所有边(x, y),更新d[y] = MIN{d[y], d[x]+w[x,y]};	//w[x,y]的值点x和y之间的权值
	}

代码实现如下:
(图的实现形式:二位数组)
在这里插入图片描述

void ShortestPath_DIJ(MGraph G, int v0, PathMartrix &P, int &D){
	int i, v, w;
	Status final[MAX_VERTEX_NUM];//final[v]为TRUE当且仅当v∈S,即已经球的从v0到v的最短距离
	//1.初始化,把任意两点间距离距离都算作无穷大,而且现在done全部为FALSE;
	//2.设定初始状态
	for(v = 0;v < G.vexnum; v++){
		final[v] = FALSE;		//表示v0和vi点间的最短距离并没有找到(vi中包括v0)
		distance[v] = G.arcs[v0][v].adj;	//各点和v0的距离放入时时变化的distance数组中
		distance[v0] = 0;final[v0] = TRUE;	//还要考虑边界因素,从v0到v0,distance[v0] = 0,也就是相当于找到了从v0到v0的最短距离了,所以final[v0] = 0;
		
		//开始主循环,每次求得v0到vi的最短距离,就把vi并入S集合中(初始状态时,S = {v0})
		for(i = 1; i < G.vexnum; i++){
			int min = INFINITY;	//min表示当前所知离v0顶点的最近距离(现在是对v0的初始化)
			for(w = 0; w < G.vexnum; ++w){
				if(!final[w])	//v0到w点的最短距离没找到,即点w不在S集合中
					if(distance[w] < min){v = w; min = distance[w];}//说明w里v0点更近
			}
			final[v] = TRUE;	//循环一边之后,就找到了min距离对应的点
			//选完点后修改distance数组
			for(w = 0; w < G.vexnum; w++){
				if(!final[w]&&((min+G.arcs[v][w].adj)<distance[w])){//看是原来的小还是纳入点后新的通路距离小,如果新点与其他点没有路径,就是INFINITY
					distance[w] = min + G.arcs[v][w].adj;
				}
			}
		}
	}
}


在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

3.Floyd算法

typedef int PathMartrix[MAX_VERTEX_NUM][MAX_VERTEX_NUM];
typedef int ShortPathTable[MAX_VERTEX_NUM][MAX_VERTEX_NUM];

void ShortestPath_FLOYD(MGraph G){
	int v, w, k;
	PathMartrix p;		//二维数组。用来描绘路径,比如
	ShortPathTable D;	//二维数组,表示出了所有边的大小(所两点之间不存在边,就把边的weight设置成infinty)
	//初始化:
	for(v = 0; v < G.vexnum; v++){
		for(w = 0; w < G.vexnum; v++){
			D[v][w] = G.arcs[v][w].adj;
			p[v][w] = w;
		}
	}
	//算法思想:两点之间的原来距离会不会因为加入一个点而减少,如果会,就改变两点之间的最小距离,而且加入的点可以不止一个,可以有n个(包括那两个点本身也是可以的)
	for(k = 0; k < G.vexnum; k++){		//假设点k为v、w两点之间的插入点
		for(v = 0; v < G.vexnum; v++){		
			for(w = 0;w < G.vexnum; 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.vexnum; v++){
		for(w = v+1; w < G.vexnum; w++){
			printf("\nV%d-->V%d weight:%d\n", v, w, D[v][w]);
			k = p[v][w];
			printf("Path:V%d", v);
			while(k != w){
				printf("-->V%d", k);
				k = p[k][w];
			}
			printf("-->%d", w);
		}
	}

}
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值