最短路径算法——简单明了的迪杰斯特拉算法(Dijkstra)

本文介绍了最短路径问题及解决算法,重点讲解了迪杰斯特拉算法(Dijkstra),阐述了其基本定义、步骤,并通过实例详细解析了算法的执行过程。Dijkstra算法用于求解从源点到任意节点的最短路径,适用于无圈网络。在实例中,展示了如何逐步找到城市1到其他城市的最短路径。
摘要由CSDN通过智能技术生成

最短路径算法——迪杰斯特拉算法(Dijkstra)

\qquad 最短路径问题是在一个网络中求一条从出发点到目的点的最短路径。
\qquad 这里会介绍求解有圈网络和无圈网络的2个算法:迪杰斯特拉算法(Dijkstra)、弗洛伊德算法(Floyd)Dijkstra算法可以求网络中从源点到任何一个节点的最短路径,而Floyd算法的应用更加广泛,可以求网络中任意两点之间的最短路径。

1迪杰斯特拉算法(Dijkstra)
1.1 各种定义

\qquad s i s_i si表示从源点到节点 i i i的最短距离, d i j d_{ij} dij(≥0)表示弧 ( i , j ) (i,j) (i,j)的长度。
\qquad 根据上述两个定义给出某一节点 j j j的标号(标号–通过数据对某一节点进行表示):
[ s j , i ] = [ s i + d i j , i ] , d i j ≥ 0 [s_j,i]=[s_i + d_{ij}, i],d_{ij}≥0 [sj,i]=[si+dij,i]dij0
\qquad 用该式表示节点 j j j [ s j , i ] [s_j,i] [sj,i]中的 s j s_j sj表示源点到节点 j j j的最短距离, i i i表示节点 j j j的“父节点”(来源节点)为 i i i,即节点 j j j的上一个节点是节点 i i i [ s i + d i j , i ] [s_i + d_{ij}, i] [si+dij,i]中的 s i + d i j s_i + d_{ij} si+dij表示源点到节点 j j j的最短距离=源点到节点 i i i的最短距离+弧 ( i , j ) (i,j) (i,j)的长度。
\qquad 在Dijkstra算法中存在两种节点 j j j的标号:暂时的、永久的。对于某一节点,如果找不到更短的路径达到该节点,则此时该节点的标号为永久的,否则则为暂时的。

1.2 步骤

第0步:对源点(节点1)进行永久地标号[0, -]. 令 i = 1 i=1 i=1.
第1步
\qquad <1>计算节点 i i i有边相连的每一个暂时节点 j j j j j j不是永久的) [ s i + d i j , i ] [s_i + d_{ij}, i] [si+dij,i]. 如果节点 j j j已经被另一个节点 k k k连接并表示为 [ s j , k ] [s_j,k] [sj,k],并且 s i + d i j < s j s_i + d_{ij}<s_j si+dij<sj,则用 [ s i + d i j , i ] [s_i + d_{ij}, i] [si+dij,i]代替 [ s j , k ] [s_j,k] [sj,k].
\qquad <2> 如果所有节点都是永久的,那么停止。否则,从所有暂时标号的节点中选择具有最短距离的进行永久标号 [ s r , l ] [s_r,l] [sr,l]。令 i = r i=r i=r,重复执行第 i i i步。

2 栗子

\qquad 下图网络中给出了城市1(节点1)和其他4个城市(节点2到节点5)之间可能的路线以及每条边的长度。求城市1到其他4个城市的最短路径。

迭代0:给节点1分配永久标号[0, -].
迭代1:节点1可以直接到达节点2、3,如下表

迭代1标号表-1
节点
标号
标号的状态
1
[0,-]
永久的
2
[0+100,1]=[100,1]
暂时的
3
[0+30,1]=[30,1]
暂时的

表中有两个暂时标号[100,1]和[30,1],其中,节点3的距离较小 s 3 = 30 s_3=30 s3=30,因此把节点3的标号的状态转变为永久的。如下表:

迭代1标号表-2
节点
标号
标号的状态
1
[0,-]
永久的
2
[0+100,1]=[100,1]
暂时的
3
[0+30,1]=[30,1]
永久的

在这里插入图片描述

迭代2:节点3可以直接到达节点4和节点5,因此各个节点的标号变为:

迭代2标号表-1
节点
标号
标号的状态
1
[0,-]
永久的
2
[0+100,1]=[100,1]
暂时的
3
[0+30,1]=[30,1]
永久的
4
[30+10,3]=[40,3]
暂时的
5
[30+60,3]=[90,3]
暂时的

\qquad 表中有三个暂时标号[100,1]、[40,3]和[90,3],其中,节点4的距离较小 s 4 = 40 s_4=40 s4=40,因此把节点4的标号的状态转变为永久的。

迭代2标号表-2
节点
标号
标号的状态
1
[0,-]
永久的
2
[0+100,1]=[100,1]
暂时的
3
[0+30,1]=[30,1]
永久的
4
[30+10,3]=[40,3]
永久的
5
[30+60,3]=[90,3]
暂时的

迭代2

迭代3:节点4可以直接到达节点2和节点5,则此时发现通过路径1-3-4-2到达节点2比路径1-2更短,即[55,4]中的55<[100,1]中的100;而路径1-3-5和1-3-4-5长度一样,得到下表

迭代3标号表-1
节点
标号
标号的状态
1
[0,-]
永久的
2
[40+15,4]=[55,4]
暂时的
3
[0+30,1]=[30,1]
永久的
4
[30+10,3]=[40,3]
永久的
5
[90,3]或[40+50,4]=[90,4]
暂时的

\qquad 此时,在暂时节点中,节点2的距离 s 2 = 55 s_2=55 s2=55最小,并且,又因为节点2只能到节点3,而节点3已经是永久标号,不能改变,因此把节点2标记为永久。此时唯一剩下的暂时节点5也只能永久标号。

迭代3标号表-2
节点
标号
标号的状态
1
[0,-]
永久的
2
[40+15,4]=[55,4]
永久的
3
[0+30,1]=[30,1]
永久的
4
[30+10,3]=[40,3]
永久的
5
[90,3]或[40+50,4]=[90,4]
永久的

迭代3

\qquad 最后按照每个节点标号进行回溯,找到节点1(源点)到其他节点的最短路径。如对于节点2,:
节点2→[55,4]→节点4→[40,3]→节点3→[30,1]→节点1,所求最短路径为1→3→4→2,距离为55.
\qquad 这是迪杰斯特拉算法,在党耀国主编的《运筹学》中,其实表现形式更加简单,有兴趣的读者可以去看一下。

迪杰斯特拉算法(Dijkstra)是一种贪心算法,用于解决最短路径问题。它可以处理有权有向图或无向图,但不允许有负权边(权重必须为非负数)。 算法思路: 1. 从起点开始,初始化所有节点的距离为无穷大,起点距离为0; 2. 将起点加入“已访问”集合; 3. 对于起点的所有邻居节点,更新它们的距离(如果通过当前节点到达邻居节点的距离小于邻居节点原有的距离,则更新邻居节点的距离); 4. 从未访问集合中选择距离起点最近的节点,加入“已访问”集合; 5. 重复步骤3和4,直到所有节点都被加入“已访问”集合或者没有与起点相连的节点。 算法实现: Dijkstra算法的实现通常使用优先队列(PriorityQueue)来维护未访问集合中距离起点最近的节点。具体实现步骤如下: 1. 创建一个空的优先队列Q,将起点加入Q中,并设置起点到自身的距离为0; 2. 创建一个数组dist[],用于保存起点到各个节点的距离,初始化为无穷大; 3. 创建一个数组visited[],用于标记节点是否被访问过,初始化为false; 4. 将dist[起点]的值设置为0; 5. 当Q不为空时,重复以下步骤: a. 从Q中取出距离起点最近的节点u; b. 如果节点u已经被访问过,则跳过此次循环; c. 将节点u标记为已访问; d. 对于节点u的每个邻居节点v,如果节点v未被访问过并且通过节点u到达节点v的距离小于dist[v],则更新dist[v]的值; e. 将节点v加入Q中。 6. 最终,dist数组中保存的就是起点到各个节点的最短距离。 Dijkstra算法的时间复杂度为O(ElogV),其中E为边数,V为节点数。这是因为算法需要对每个节点的所有邻居节点进行遍历,而优先队列的插入和删除操作的时间复杂度为O(logV)。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值