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

Dijkstra算法是一种单源最短路径算法,且算法要求图中不存在负权边,其伪代码如表 S 1 S1 S1 所示。假设 G = ( V , E ) G = (V, E) G=(V,E) 是一个带权的有向图,在图 G G G 中把顶点集合 V V V 分为两组:第一组是已经求出最短路径的顶点集合 S S S,初始的 S S S 只有一个顶点(源点 v 1 v_1 v1),在后续的解算过程中,每求解一条最短路径时,将其顶点加入到集合 S S S,直至所有的顶点都在 S S S 中,结束算法;第二组是还未被解算的顶点集合 U U U,将 U U U 中的顶点按照路径长度的递增顺序依次添加到顶点集合 S S S 中,且需要满足从源点 v 1 v_1 v1 到集合 S S S 中每个顶点的最短距离要小于等于从源点 v 1 v_1 v1 到集合 U 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) G=(V,E) 是一个带权的有向图,其中 V V V = = = { v 1 , \{v_1, {v1, v 2 , v_2, v2, v 3 , v_3, v3, v 4 , v_4, v4, v 5 , v_5, v5, v 6 , v_6, v6, v 7 } v_7\} v7} E = < v i , v j > E = {<v_i, v_j>} E=<vi,vj>, 所有的 i , j = [ 1 , 7 ] i, j = [1, 7] i,j=[1,7],求解以顶点 v 1 v_1 v1 为源点的各个顶点的最短距离,算法示例步骤:

  1. 初始时, S S S 中只有一个顶点(源点 v 1 v_1 v1), S = v 1 ( < v 1 , v 1 > ) S = {v_1(<v_1, v_1>)} S=v1(<v1,v1>),即 S = v 1 ( 0 ) S = {v_1(0)} S=v1(0);此时 U U U 中包含除 v 1 v_1 v1 以外的所有点,若 v 1 v_1 v1 U U U 中的顶点 u u u 有边,则 < v 1 , u > <v_1, u> <v1,u> 有权值,反之, < v 1 , u > <v_1, u> <v1,u> 的权值为 ∞ ∞ U = v i ( < v 1 , v i > ) U = {v_i(<v_1, v_i>)} U=vi(<v1,vi>), 所有的 i = [ 2 , 7 ] i = [2, 7] i=[2,7],即 U U U = = = { v 2 ( 12 ) , \{v_2(12), {v2(12), v 3 ( 7 ) , v_3(7), v3(7), v 4 ( ∞ ) , v_4(∞), v4(), v 5 ( 23 ) , v_5(23), v5(23), v 6 ( ∞ ) , v_6(∞), v6(), v 7 ( 26 ) } v_7(26)\} v7(26)}
  2. U U U 中取出最短的顶点 v 3 v_3 v3,其权值为 7 7 7,将 v 3 v_3 v3 加入 S S S 中,此时 S = { v 1 ( 0 ) , S = \{v_1(0), S={v1(0), v 3 ( 7 ) } v_3(7)\} v3(7)};由于 < v 3 ,   v 4 > <v_3, ~v_4> <v3, v4> 的权值为 6 6 6 < v 1 , v 4 > <v_1, v_4> <v1,v4> = = = < v 1 , v 3 > <v_1, v_3> <v1,v3> + + + < v 3 , v 4 > <v_3, v_4> <v3,v4> = 13 = 13 =13,小于 ∞ ∞ ;即 U U U = = = { v 2 ( 12 ) , \{v_2(12), {v2(12), v 4 ( 13 ) , v_4(13), v4(13), v 5 ( 23 ) , v_5(23), v5(23), v 6 ( ∞ ) , v_6(∞), v6(), v 7 ( 26 ) } v_7(26)\} v7(26)}
  3. U U U 中取出最短的顶点 v 2 v_2 v2,其权值为 12 12 12,将 v 2 v_2 v2 加入 S S S 中,此时 S = { v 1 ( 0 ) , v 3 ( 7 ) , v 2 ( 12 ) } S = \{v_1(0), v_3(7), v_2(12)\} S={v1(0),v3(7),v2(12)};由于 < v 2 , v 6 > <v_2, v_6> <v2,v6> 的权值为 11 11 11 < v 1 , v 6 > <v_1, v_6> <v1,v6> = = = < v 1 , v 2 > <v_1,v_2> <v1,v2> + + + < v 2 , v 6 > <v_2, v_6> <v2,v6> = = = 23 < ∞ 23 < ∞ 23<;由于 < v 2 , v 7 > <v_2, v_7> <v2,v7> 的权值为6, < v 1 , v 7 > <v_1, v_7> <v1,v7> = = = < v 1 , v 2 > <v_1, v_2> <v1,v2> + + + < v 2 , v 7 > <v_2, v_7> <v2,v7> = 18 < 26 = 18 < 26 =18<26;即 U = U = U= { v 4 ( 13 ) , \{v_4(13), {v4(13), v 5 ( 23 ) , v_5(23), v5(23), v 6 ( 23 ) , v_6(23), v6(23), v 7 ( 18 ) } v_7(18)\} v7(18)}
  4. U U U 中取出最短的顶点 v 4 v_4 v4,其权值为 13 13 13,将 v 4 v_4 v4 加入 S S S 中,此时 S S S = { v 1 ( 0 ) , = \{v_1(0), ={v1(0), v 3 ( 7 ) , v_3(7), v3(7), v 2 ( 12 ) , v_2(12), v2(12), v 4 ( 13 ) } v_4(13)\} v4(13)};由于 < v 4 , v 5 > <v_4, v_5> <v4,v5> 的权值为 6 6 6 < v 1 , v 5 > <v_1, v_5> <v1,v5> = < v 1 , v 4 > = <v_1, v_4> =<v1,v4> + < v 4 , v 5 > + <v_4, v_5> +<v4,v5> = 19 < 23 = 19 < 23 =19<23;即 U = U = U= { v 5 ( 19 ) , \{v_5(19), {v5(19), v 6 ( 23 ) , v_6(23), v6(23), v 7 ( 18 ) } v_7(18)\} v7(18)}
  5. U U U 中取出最短的顶点 v 7 v_7 v7,其权值为 18 18 18,将 v 7 v_7 v7 加入 S S S 中,此时 S = S = S= { v 1 ( 0 ) , \{v_1(0), {v1(0), v 3 ( 7 ) , v_3(7), v3(7), v 2 ( 12 ) , v_2(12), v2(12), v 4 ( 13 ) , v_4(13), v4(13), v 7 ( 18 ) } v_7(18)\} v7(18)} U = U = U= { v 5 ( 19 ) , \{v_5(19), {v5(19), v 6 ( 23 ) } v_6(23)\} v6(23)}
  6. U U U 中取出最短的顶点 v 5 v_5 v5,其权值为 19 19 19,将 v 5 v_5 v5 加入 S S S 中,此时 S = S = S= { v 1 ( 0 ) , \{v_1(0), {v1(0), v 3 ( 7 ) , v_3(7), v3(7), v 2 ( 12 ) , v_2(12), v2(12), v 4 ( 13 ) , v_4(13), v4(13), v 7 ( 18 ) , v_7(18), v7(18), v 5 ( 19 ) } v_5(19)\} v5(19)};由于 < v 5 , v 6 > <v_5, v_6> <v5,v6> 的权值为 2 2 2 < v 1 , v 6 > <v_1, v_6> <v1,v6> = < v 1 , v 5 > = <v_1, v_5> =<v1,v5> + < v 5 , v 6 > + <v_5, v_6> +<v5,v6> = 21 < 23 = 21 < 23 =21<23;即 U = { v 6 ( 21 ) } U = \{v_6(21)\} U={v6(21)}
  7. U U U 中取出最短的顶点 v 6 v_6 v6,其权值为 21 21 21,将 v 6 v_6 v6 加入 S S S 中,此时 S S S = { v 1 ( 0 ) , = \{v_1(0), ={v1(0), v 3 ( 7 ) , v_3(7), v3(7), v 2 ( 12 ) , v_2(12), v2(12), v 4 ( 13 ) , v_4(13), v4(13), v 7 ( 18 ) , v_7(18), v7(18), v 5 ( 19 ) , v_5(19), v5(19), v 6 ( 21 ) } v_6(21)\} v6(21)} U = ∅ U = ∅ U=
  8. 此时 U = ∅ U = ∅ U=,已经获取到以 v 1 v_1 v1 为源点的各个顶点的最短距离,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;
}
  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A-Chin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值