算法和数据结构-最短路径算法Dijsktra

1.算法思想:

 Dijsktra:确定一个起始点,找出该点到图中其余所有点路程的最小值,要求图中累加和为负数的环,可以有权值为负数的边
 假设一个图如下,A为起始点:
         D
     9/  |  \19
     /  7|   \
    A--- C ---E
     \15 | 14/
    3 \ 2|  /200
         B
 算法:
    1. 初始化一个表格(~表示无穷大)A  B  C  D  E
       A  0  ~  ~  ~  ~
    2. 找出此时最小值对应的点为中转点(锁定点除外),选择A且锁定该点不再修改表格中A对应的值
    3. A经过A点可以得到AA+AD=AD,AA+AC=AC,AA+AB=AB,将得到的距离和原表格中的值去较小值更新表格:
          A  B  C  D  E
       A  0  3  15 9  ~
    4. 找出此时最小值对应的点为中转点(锁定点除外),选择B且锁定该点不再修改表格中B对应的值
    5. A经过B点可以得到AB+BC=AC,AB+BE=AE,将得到的距离和原表格中的值去较小值更新表格:
          A  B  C  D  E
       A  0  3  5  9 203
    6. 找出此时最小值对应的点为中转点(锁定点除外),选择C且锁定该点不再修改表格中C对应的值
    7. A经过C点可以得到AC+CE=AE,AC+CD=AD,将得到的距离和原表格中的值去较小值更新表格:
          A  B  C  D  E
       A  0  3  5  9  29
    8. 找出此时最小值对应的点为中转点(锁定点除外),选择D且锁定该点不再修改表格中D对应的值
    9. A经过D点可以得到AD+DE=AE,将得到的距离和原表格中的值去较小值更新表格:
          A  B  C  D  E
       A  0  3  5  9  28

2.代码实现:

public class Dijsktra {
    // 找出从head出发到所有点的最小距离
    public static HashMap<Node, Integer> dijsktra(Node head) {
        // key表示从head出发到达的点;value表示从head出发到key的最小距离
        // 如果distanceMap中没有某个点的记录,说明从head出发到该点的距离为无穷大
        HashMap<Node, Integer> distanceMap = new HashMap<>();

        distanceMap.put(head, 0);  // head到自己的距离为0

        // 存储已经被锁定的点
        HashSet<Node> selectedNodes = new HashSet<>();
        Node minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);

        // 以minNode为中转点
        while (minNode != null) {
            int distance = distanceMap.get(minNode);
            // 遍历和minNode相连的边,通过每条边的to节点确定以minNode为中转点的情况下,计数从head出发到to节点的距离,再和原来记录的距离进行比较
            for (Edge edge : minNode.edges) {
                Node toNode = edge.to;
                // 如果distanceMap中没有某个点的记录,说明从head出发到该点的距离为无穷大,更新后的距离肯定要小于无穷大的,不需要和原来的比较
                if (!distanceMap.containsKey(toNode)) {
                    distanceMap.put(toNode, distance + edge.weight);
                } else {
                    distanceMap.put(toNode, Math.min(distanceMap.get(toNode), distance + edge.weight));
                }
            }
            // 锁定minNode
            selectedNodes.add(minNode);
            // 选择下一个中转点
            minNode = getMinDistanceAndUnselectedNode(distanceMap, selectedNodes);

        }

        return distanceMap;
    }

    // 从distanceMap中选择value值最小的记录,且该记录中的key值对应的节点未在touchNodes中,即未被锁定
    public static Node getMinDistanceAndUnselectedNode(
            HashMap<Node, Integer> distanceMap,
            HashSet<Node> touchNodes) {
        Node minNode = null;
        int minDistance = Integer.MAX_VALUE;
        for (Entry<Node, Integer> entry : distanceMap.entrySet()) {
            Node node = entry.getKey();
            int distance = entry.getValue();
            if (distance < minDistance && !touchNodes.contains(node)) {
                minNode = node;
                minDistance = distance;
            }
        }

        return minNode;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值