11.贪心算法入门-----Dijkstra算法详解

Dijkstra算法详细(单源最短路径算法)

对于dijkstra算法,很多人可能感觉熟悉而又陌生,可能大部分人比较了解bfs和dfs,而对dijkstra和floyd算法可能知道大概是图论中的某个算法,但是可能不清楚其中的作用和原理,又或许,你曾经感觉它很难,那么,这个时候正适合你重新认识它。

Dijkstra算法是干啥的?
在这里插入图片描述

Dijkstra是用来求单源最短路径的

就拿上图来说,假如城市之间直达的路径和长度已知,那么可以使用dijkstra算法计算北京到图中所有节点的最短距离。

单源什么意思?

从一个顶点出发,Dijkstra算法只能求一个顶点到其他点的最短距离而不能任意两点。

和bfs求的最短路径有什么区别?

bfs求的与其说是路径,不如说是次数。因为bfs他是按照队列一次一次进行加入相邻的点,
而两点之间没有权值或者权值相等(代价相同)。处理的更多是偏向迷宫类的这种都是只能走邻居(不排除特例)。

Dijkstra在处理具体实例的应用还是很多的,因为具体的问题其实带权更多一些。

比如一个城市有多个乡镇,乡镇可能有道路,也可能没有,整个乡镇联通,如果想计算每个乡镇
到a镇的最短路径,那么Dijkstra就派上了用场。

算法分析

对于一个算法,首先要理解它的运行流程。
对于一个Dijkstra算法而言,前提是它的前提条件和环境:

一个连通图,若干节点,节点可能有数值,但是路径一定有权值。并且路径不能为负。否则Dijkstra就不适用。

Dijkstra的核心思想是贪心算法的思想。

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,
不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备
无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

对于贪心算法,在很多情况都能用到。下面举几个不恰当的例子!

打个比方,吃自助餐,目标是吃回本,那么胃有限那么每次都挑最贵的吃。

上学时,麻麻说只能带5个苹果,你想带最多,那么选五个苹果你每次都选最大的那个
五次下来你就选的最重的那个。

不难发现上面的策略虽然没有很强的理论数学依据,或者不太好说明。但是事实规律就是那样,并且对于贪心问题大部分都需要排序,还可能会遇到类排序。并且一个物体可能有多个属性,不同问题需要按照不同属性进行排序,操作。

那么我们的Dijkstra是如何贪心的呢?对于一个点,求图中所有点的最短路径,如果没有正确的方法胡乱想确实很难算出来,并且如果暴力匹配复杂度呈指数级上升不适合解决实际问题。

那么我们该怎么想呢?

Dijkstra算法的前提:

首先,Dijkstra处理的是带正权值的有权图,那么,就需要一个二维数组(如果空间大用list数组)存储各个点到达(边)的权值大小。(邻接矩阵或者邻接表存储)
其次,还需要一个boolean数组判断那些点已经确定最短长度,那些点没有确定。int数组记录距离(在算法执行过程可能被多次更新)。
需要优先队列加入已经确定点的周围点。每次抛出确定最短路径的那个并且确定最短,直到所有点路径确定最短为止。

简单的概括流程为:

1. 一般从选定点开始抛入优先队列。(路径一般为0),boolean数组标记0的位置(最短为0) , 
然后0周围连通的点抛入优先队列中(可能是node类),并把各个点的距离记录到对应数组内
(如果小于就更新,大于就不动,初始第一次是无穷大肯定会更新),第一次就结束了
2.从队列中抛出距离最近的那个点B(第一次就是0周围邻居)。这个点距离一定是最近的
(所有权值都是正的,点的距离只能越来越长。)标记这个点为true,并且将这个点的邻居加入队列
(下一次确定的最短点在前面未确定和这个点邻居中产生),并更新通过B点计算各个位置的长度
,如果小于则更新!

在这里插入图片描述

重复2的操作,直到所有点都确定。

在这里插入图片描述

算法实现(Java)

package Graph;

import java.util.ArrayDeque;
import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Scanner;

public class dijkstra {
   
	
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值