《算法图解》读书笔记 - 狄克斯特拉算法(Dijkstra)

Posted Leida_wanglin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《算法图解》读书笔记 - 狄克斯特拉算法(Dijkstra)相关的知识,希望对你有一定的参考价值。

《算法图解》读书笔记 - 狄克斯特拉算法(Dijkstra)

应用于有向加权图中前往X的最短路径。


狄克斯特拉算法步骤
(1)找出“最便宜”的节点,即可在最短时间内到达的节点。
(2)更新该节点的邻居的开销。
(3)重复这个过程,直到对图中的每个节点都这样做了。
(4)计算最终路径。

第一步:找出最便宜的节点。你站在起点,不知道该前往节点A还是前往节点B。前往这两个节点都要多长时间呢?

前往节点A需要6分钟,而前往节点B需要2分钟。至于前往其他节点,你
还不知道需要多长时间。

由于你还不知道前往终点需要多长时间,因此你假设为无穷大(这样做的
原因你马上就会明白)。节点B是最近的——2分钟就能达到。

第二步:计算经节点B前往其各个邻居所需的时间。

你刚找到了一条前往节点A的更短路径!直接前往节点A需要6分钟。

但经由节点B前往节点A只需5分钟!

对于节点B的邻居,如果找到前往它的更短路径,就更新其开销。在这里,你找到了:
 前往节点A的更短路径(时间从6分钟缩短到5分钟);
 前往终点的更短路径(时间从无穷大缩短到7分钟)。

第三步:重复!
重复第一步:找出可在最短时间内前往的节点。你对节点B执行了第二步,除节点B外,可在最短时间内前往的节点是节点A。

重复第二步:更新节点A的所有邻居的开销。

你发现前往终点的时间为6分钟!
你对每个节点都运行了狄克斯特拉算法(无需对终点这样做)。现在,你知道:
 前往节点B需要2分钟;
 前往节点A需要5分钟;
 前往终点需要6分钟。

最后一步——计算最终路径将留到下一节去介绍,这里先直接将最终路径告诉你。

Java代码实现Dijkstra算法


我在这建立三个散列表

1.graph存节点与节点和节点之间的边的值
2.costs存起点与各个节点的权重
3.parents存父节点

小编在这里写的是Java思想,存在一个问题就是HashMap<String, HashMap<String, Integer>>会出现相同Key的Value会被覆盖的问题还没有解决,所以此代码只提供思路。

public class Dijkstra 

    private static HashMap<String, HashMap<String, Integer>> graph = new HashMap<>();

    private static HashMap<String, Integer> costs = new HashMap<>();

    private static HashMap<String, String> parents = new HashMap<>();

    private static List<String> processed = new ArrayList<>();

    public static void dijkstra() 
        //在未处理的节点中找出开销最小的节点
        String node = findLowestCostNode(costs);
        //这个while循环在所有节点都被处理过后结束
        while (node != null) 
            Integer cost = costs.get(node);
            HashMap<String, Integer> neighbors = graph.get(node);
            //遍历当前节点的所有邻居
            for (String n : neighbors.keySet()) 
                Integer new_cost = cost + neighbors.get(n);
                //如果经当前节点前往该邻居更近
                if (costs.get(n) > new_cost) 
                    //就更新该邻居的开销
                    costs.put(n, new_cost);
                    //同时将该邻居的父节点设置为当前节点
                    parents.put(n, node);
                
            
            //将当前节点标记为处理过
            processed.add(node);
            //找出接下来要处理的节点,并循环
            node = findLowestCostNode(costs);
        
    

    //找出开销最低的节点
    public static String findLowestCostNode(HashMap<String, Integer> costs) 
        Integer lowest_cost = Integer.MAX_VALUE;
        String lowest_cost_node = null;
        //遍历所有的节点
        for (String node : costs.keySet()) 
            Integer cost = costs.get(node);
            //如果当前节点的开销更低且未处理过
            if (cost < lowest_cost && parents.containsKey(node) == false) 
                //就将其视为开销最低的节点
                lowest_cost = cost;
                lowest_cost_node = node;
            
        
        return lowest_cost_node;
    

    public static void main(String[] args) 

        graph.put("start", new HashMap<String, Integer>()put("a", 6););
        graph.put("start", new HashMap<String, Integer>()put("b", 2););
        graph.put("a", new HashMap<String, Integer>()put("fin", 1););
        graph.put("b", new HashMap<String, Integer>()put("a", 3););
        graph.put("b", new HashMap<String, Integer>()put("fin", 5););
        graph.put("fin", new HashMap<>());

        costs.put("a", 6);
        costs.put("b", 2);
        costs.put("fin", Integer.MAX_VALUE);

        parents.put("a", "start");
        parents.put("b", "start");
        parents.put("fin", null);

        dijkstra();

        System.out.println(costs.get("fin"));
    

以上是关于《算法图解》读书笔记 - 狄克斯特拉算法(Dijkstra)的主要内容,如果未能解决你的问题,请参考以下文章

算法作业13——《算法图解》读书笔记

算法图解-狄克斯特拉算法

算法之狄克斯特拉算法 --《图解算法》

[算法读书笔记C++,搜索与图论]dijkstra算法

[算法读书笔记C++,搜索与图论]dijkstra算法

狄克斯特拉(Dijkstra)算法详解