Dijkstra最短路径算法(附C++代码)

Dijkstra算法是一种单源最短路径算法,且算法要求图中不存在负权边,其伪代码如表 S 1 S1 所示。假设 G = ( V , E ) G = (V, E) 是一个带权的有向图,在图 G G 中把顶点集合 V V 分为两组:第一组是已经求出最短路径的顶点集合 S S ,初始的 S S 只有一个顶点(源点 v 1 v_1 ),在后续的解算过程中,每求解一条最短路径时,将其顶点加入到集合 S S ,直至所有的顶点都在 S S 中,结束算法;第二组是还未被解算的顶点集合 U U ,将 U U 中的顶点按照路径长度的递增顺序依次添加到顶点集合 S S 中,且需要满足从源点 v 1 v_1 到集合 S S 中每个顶点的最短距离要小于等于从源点 v 1 v_1 到集合 U U 中任何一个顶点的最短距离。

表S1 Dijkstra算法伪代码 
for each node v	
	dis(v)+∞	
	previous (v) ← undefined	
	dis(source)0	
	while num(S) < n	▷ S为顶点集合
		u ← node with smallest distance	
		Remove u	
		for each node v in S	
			alt ← dis(u) + dis(u,v)	
			if alt < dis(v) then	
				dis(v) ← alt	▷ 更新距离
				previous(v) ← u	

有向图G
如上图所示, G = ( V , E ) G = (V, E) 是一个带权的有向图,其中 V V = = { v 1 , \{v_1, v 2 , v_2, v 3 , v_3, v 4 , v_4, v 5 , v_5, v 6 , v_6, v 7 } v_7\} E = < v i , v j > E = {<v_i, v_j>} , 所有的 i , j = [ 1 , 7 ] i, j = [1, 7] ,求解以顶点 v 1 v_1 为源点的各个顶点的最短距离,算法示例步骤:

  1. 初始时, S S 中只有一个顶点(源点 v 1 v_1 ), S = v 1 ( < v 1 , v 1 > ) S = {v_1(<v_1, v_1>)} ,即 S = v 1 ( 0 ) S = {v_1(0)} ;此时 U U 中包含除 v 1 v_1 以外的所有点,若 v 1 v_1 U U 中的顶点 u u 有边,则 < v 1 , u > <v_1, u> 有权值,反之, < v 1 , u > <v_1, u> 的权值为 U = v i ( < v 1 , v i > ) U = {v_i(<v_1, v_i>)} , 所有的 i = [ 2 , 7 ] i = [2, 7] ,即 U U = = { v 2 ( 12 ) , \{v_2(12), v 3 ( 7 ) , v_3(7), v 4 ( ) , v_4(∞), v 5 ( 23 ) , v_5(23), v 6 ( ) , v_6(∞), v 7 ( 26 ) } v_7(26)\}
  2. U U 中取出最短的顶点 v 3 v_3 ,其权值为 7 7 ,将 v 3 v_3 加入 S S 中,此时 S = { v 1 ( 0 ) , S = \{v_1(0), v 3 ( 7 ) } v_3(7)\} ;由于 < v 3 ,   v 4 > <v_3, ~v_4> 的权值为 6 6 < v 1 , v 4 > <v_1, v_4> = = < v 1 , v 3 > <v_1, v_3> + + < v 3 , v 4 > <v_3, v_4> = 13 = 13 ,小于 ;即 U U = = { v 2 ( 12 ) , \{v_2(12), v 4 ( 13 ) , v_4(13), v 5 ( 23 ) , v_5(23), v 6 ( ) , v_6(∞), v 7 ( 26 ) } v_7(26)\}
  3. U U 中取出最短的顶点 v 2 v_2 ,其权值为 12 12 ,将 v 2 v_2 加入 S S 中,此时 S = { v 1 ( 0 ) , v 3 ( 7 ) , v 2 ( 12 ) } S = \{v_1(0), v_3(7), v_2(12)\} ;由于 < v 2 , v 6 > <v_2, v_6> 的权值为 11 11 < v 1 , v 6 > <v_1, v_6> = = < v 1 , v 2 > <v_1,v_2> + + < v 2 , v 6 > <v_2, v_6> = = 23 < 23 < ∞ ;由于 < v 2 , v 7 > <v_2, v_7> 的权值为6, < v 1 , v 7 > <v_1, v_7> = = < v 1 , v 2 > <v_1, v_2> + + < v 2 , v 7 > <v_2, v_7> = 18 < 26 = 18 < 26 ;即 U = U = { v 4 ( 13 ) , \{v_4(13), v 5 ( 23 ) , v_5(23), v 6 ( 23 ) , v_6(23), v 7 ( 18 ) } v_7(18)\}
  4. U U 中取出最短的顶点 v 4 v_4 ,其权值为 13 13 ,将 v 4 v_4 加入 S S 中,此时 S S = { v 1 ( 0 ) , = \{v_1(0), v 3 ( 7 ) , v_3(7), v 2 ( 12 ) , v_2(12), v 4 ( 13 ) } v_4(13)\} ;由于 < v 4 , v 5 > <v_4, v_5> 的权值为 6 6 < v 1 , v 5 > <v_1, v_5> = < v 1 , v 4 > = <v_1, v_4> + < v 4 , v 5 > + <v_4, v_5> = 19 < 23 = 19 < 23 ;即 U = U = { v 5 ( 19 ) , \{v_5(19), v 6 ( 23 ) , v_6(23), v 7 ( 18 ) } v_7(18)\}
  5. U U 中取出最短的顶点 v 7 v_7 ,其权值为 18 18 ,将 v 7 v_7 加入 S S 中,此时 S = S = { v 1 ( 0 ) , \{v_1(0), v 3 ( 7 ) , v_3(7), v 2 ( 12 ) , v_2(12), v 4 ( 13 ) , v_4(13), v 7 ( 18 ) } v_7(18)\} U = U = { v 5 ( 19 ) , \{v_5(19), v 6 ( 23 ) } v_6(23)\}
  6. U U 中取出最短的顶点 v 5 v_5 ,其权值为 19 19 ,将 v 5 v_5 加入 S S 中,此时 S = S = { v 1 ( 0 ) , \{v_1(0), v 3 ( 7 ) , v_3(7), v 2 ( 12 ) , v_2(12), v 4 ( 13 ) , v_4(13), v 7 ( 18 ) , v_7(18), v 5 ( 19 ) } v_5(19)\} ;由于 < v 5 , v 6 > <v_5, v_6> 的权值为 2 2 < v 1 , v 6 > <v_1, v_6> = < v 1 , v 5 > = <v_1, v_5> + < v 5 , v 6 > + <v_5, v_6> = 21 < 23 = 21 < 23 ;即 U = { v 6 ( 21 ) } U = \{v_6(21)\}
  7. U U 中取出最短的顶点 v 6 v_6 ,其权值为 21 21 ,将 v 6 v_6 加入 S S 中,此时 S S = { v 1 ( 0 ) , = \{v_1(0), v 3 ( 7 ) , v_3(7), v 2 ( 12 ) , v_2(12), v 4 ( 13 ) , v_4(13), v 7 ( 18 ) , v_7(18), v 5 ( 19 ) , v_5(19), v 6 ( 21 ) } v_6(21)\} U = U = ∅
  8. 此时 U = U = ∅ ,已经获取到以 v 1 v_1 为源点的各个顶点的最短距离,Dijkstra算法结束。

附C++代码:

#define DB_MAX 100000000.0

bool dijkstra(float** pathvalue, int pointnum, int v, float* dist, int* path)
{
	int n = pointnum;
	bool *S = new bool[n];
	int i, j, k;
	float w, min;

	for (i = 0; i < n; ++i)
	{
		dist[i] = pathvalue[v][i];
		S[i] = false;
		if(i != v && dist[i] < DB_MAX)
			path[i] = v;
		else
			path[i] = -1;
	}

	S[v] = true;
	dist[v] = 0;
	for (i = 0; i < n-1; ++i)
	{
		min = DB_MAX;
		int u = v;
		for (j = 0; j < n; ++j)
		{
			if(S[j] == false && dist[j] < min)
			{
				u = j;
				min = dist[j];
			}
		}
		S[u] = true;
		for (k = 0; k < n; ++k)
		{
			w = pathvalue[u][k];
			if(S[k] == false && w < DB_MAX && dist[u] + w < dist[k])
			{
				dist[k] = dist[u] + w;
				path[k] = u;
			}
		}
	}
	return true;
}
发布了35 篇原创文章 · 获赞 37 · 访问量 4276

猜你喜欢

转载自blog.csdn.net/L_J_Kin/article/details/103061420
今日推荐