算法——单源最短路径:Bellman-Ford算法、Dijkstra算法

前言

    在最短路径问题中,约定图《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》是一个带权值的有向图。最短路径是解决两节点之间的最小代价问题。最短路径有几种分类:单源最短路径;单目标最短路径;单节点对最短路径;所有节点对最短路径。下面记录单源最短路径问题。

单源最短路径

定义:

   单源最短路径是给定一个图《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,希望从一个源节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》到每个节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》的最短路径。

单源最短路径的算法

    在介绍算法之前,首先必须介绍下松弛操作,在整个算法中,松弛操作是很重要的,松弛操作的目的是要获得最短路径估计《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》;在任何操作之前必须对节点进行初始化操作,松弛过程:将节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》到节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》之间的最短路径距离加上节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》到节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》之间的边权值,并与当前节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》到节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》的最短路径估计进行比较,如果前者较小,则更新最短路径估计《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》和前驱《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》属性。

//初始化操作
INITIALIZE-SINGLE-SOURCE(G,s)
	for each vertex v ∈ G.V 	
		v.d = inf				
		v.front = NIL			
	s.d = 0
//松弛操作
RELAX(u,v,w) //w是权值函数
	if v.d > u.d + w(u,v)
		v.d = u.d + w(u,v)
		v.front = u


松弛操作过程结构:

《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》    
    根据对图的边进行不同松弛次数和次序,解决单源最短路径问题,下面介绍两种算法:Bellman-Ford算法和Dijkstra算法。

Bellman-Ford算法

    该算法适用于边权值可为负,但不能有权值为负带有环路的图
因为如果包含环路,且环路的权值和为正的,那么去掉这个环路,可以得到更短的路径;如果环路的权值是负的,那么肯定没有解
。该算法是对每一条边进行《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》次松弛,通过对边的松弛操作渐近地降低从源节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》到每个节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》的最短路径估计值《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,直到该估计值与实际的最短路径权重《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》相同为止。若该算法的输入图不包含可以从源节点到达的权重为负值的环路,则返回TRUE。
步骤:

  1. 初始化图的每个节点;
  2. 对每条边进行《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》次松弛操作;
  3. 判断最短路径估计值是否与实际权重相同,若相同则返回TRUE,否则返回FALSE;

//Bellman-Ford算法
BELLMAN-FORD(G,w,s)
	INITIALIZE-SINGLE-SOURCE(G,s)
	for i = 1 to |G.V|-1
		for each edge (u,v) ∈ G.E 	
			RELAX(u,v,w)
	for each edge (u,v) ∈ G.E 
		if v.d > u.d + w(u,v)
			return FALSE
	return TRUE


procedure BellmanFord(list vertices, list edges, vertex source)
   // 该实现读入边和节点的列表,并向两个数组(distance和predecessor)中写入最短路径信息

   // 步骤1:初始化图
   for each vertex v in vertices:
       if v is source then distance[v] := 0
       else distance[v] := infinity
       predecessor[v] := null

   // 步骤2:重复对每一条边进行松弛操作
   for i from 1 to size(vertices)-1:
       for each edge (u, v) with weight w in edges:
           if distance[u] + w < distance[v]:
               distance[v] := distance[u] + w
               predecessor[v] := u

   // 步骤3:检查负权环
   for each edge (u, v) with weight w in edges:
       if distance[u] + w < distance[v]:
           error "图包含了负权环"

举例:算法执行过程中,源节点为
《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,图a是初始化后的结果。每一次松弛操作对边的处理次序都是:
《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,操作的时候记住要按照顺序进行松弛,例如从图a到图b最短路径估计值的变化过程是:第二行:表示初始化结果;第三行:表示按顺序执行完《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》后的结果;第四行:表示执行完《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》的结果;

stxyz
0
06
067

《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》

Dijkstra算法

       Dijkstra
算法要求所有边的权重都为非负。该算法在执行的过程中维持的关键信息是一组节点集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,从源节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》到该集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》的每个节点之间都是最短路径已被找到。算法重复从节点集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》中选择最短路径估计最小的节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,将节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》加入到集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,然后对从节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》发出的边进行松弛。

//Dijkstra算法
Dijkstra(G,w,s)
	INITIALIZE-SINGLE-SOURCE(G,s)
	S = ∅
	Q = G.V
	while Q ≠ ∅
		u = EXTRACT-MIN(Q)
		S = S ∪{u}
		for each vertex v∈G.Adj[u]
			RELAX(u,v,w)

   举例:执行过程中,刚开始集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》为空,则把集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》中最短路径估计最小的节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》加入到集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》
然后对从节点
《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》
发出的边进行松弛。
第一步(图b):将节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》加入集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,并对节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》所发出的边进行松弛操作;
第二步(图c):在集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》最短路径估计最小的节点为《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,将节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》加入到集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》并对节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》所发出的边进行松弛操作;
第三步(图d):在集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》最短路径估计最小的节点为《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,将节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》加入到集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,并对节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》所发出的边进行松弛操作;
第四步(图e):在集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》最短路径估计最小的节点为《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,将节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》加入到集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,并对节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》所发出的边进行松弛操作;
第五步(图f):在集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》最短路径估计最小的节点为《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,将节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》加入到集合《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》,并对节点《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》所发出的边进行松弛操作;

《算法——单源最短路径:Bellman-Ford算法、Dijkstra算法》

    原文作者:Bellman - ford算法
    原文地址: https://blog.csdn.net/chenhanzhun/article/details/39051839
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞