最近路径算法实现——Dijkstra

先上代码

package wetalk;

import java.util.*;
import java.util.stream.Collectors;

public class DijkstraTest {

    public static void main(String[] args) {
        System.setProperty("mode", "direct");
        Map<String, Map<String, Integer>> originalInfo1 = new HashMap<>();
        Map<String, Integer> ad = new HashMap<>();
        ad.put("B", 12);
        ad.put("F", 16);
        ad.put("G", 14);
        originalInfo1.put("A", ad);

        Map<String, Integer> bd = new HashMap<>();
        bd.put("C", 10);
        bd.put("F", 7);
        originalInfo1.put("B", bd);

        Map<String, Integer> cd = new HashMap<>();
        cd.put("F", 6);
        cd.put("E", 5);
        cd.put("D", 3);
        originalInfo1.put("C", cd);

        Map<String, Integer> dd = new HashMap<>();
        dd.put("E", 4);
        originalInfo1.put("D", dd);

        Map<String, Integer> ed = new HashMap<>();
        ed.put("F", 2);
        ed.put("G", 8);
        originalInfo1.put("E", ed);

        Map<String, Integer> fd = new HashMap<>();
        fd.put("G", 9);
        originalInfo1.put("F", fd);
        Map<String, Integer> gd = new HashMap<>();
        originalInfo1.put("G", gd);
        System.setProperty("mode", "nonDirect");
        dijkstra(originalInfo1, "D", "A");
        dijkstra(originalInfo1, "A", "D");


        Map<String, Map<String, Integer>> originalInfo2 = new HashMap<>();
        Map<String, Integer> v1d = new HashMap<>();
        v1d.put("v3", 10);
        v1d.put("v5", 30);
        v1d.put("v6", 100);
        originalInfo2.put("v1", v1d);

        Map<String, Integer> v2d = new HashMap<>();
        v2d.put("v3", 5);
        originalInfo2.put("v2", v2d);

        Map<String, Integer> v3d = new HashMap<>();
        v3d.put("v4", 50);
        originalInfo2.put("v3", v3d);

        Map<String, Integer> v4d = new HashMap<>();
        v4d.put("v6", 10);
        originalInfo2.put("v4", v4d);

        Map<String, Integer> v5d = new HashMap<>();
        v5d.put("v4", 20);
        v5d.put("v6", 60);
        originalInfo2.put("v5", v5d);

        Map<String, Integer> v6d = new HashMap<>();
        originalInfo2.put("v6", v6d);
        System.setProperty("mode", "direct");
        dijkstra(originalInfo2, "v1", "v6");
        dijkstra(originalInfo2, "v6", "v1");
    }

    private static void dijkstra(Map<String, Map<String, Integer>> originalInfo, String firstNode, String lastNode) {
        Map<String, String> preNodes = new HashMap<>();
        Map<String, Integer> distanceInfo = new HashMap<>();
        Map<String, Boolean> flags = new HashMap<>();
        String mode = System.getProperty("mode", "nonDirect");
        originalInfo.forEach((node, d) -> {
            if (mode.equals("nonDirect")) {
                d.forEach((k, v) -> originalInfo.get(k).put(node, v));
            }
            flags.put(node, Boolean.FALSE);
            distanceInfo.put(node, Integer.MAX_VALUE);
        });
        distanceInfo.put(firstNode, 0);
        flags.put(firstNode, Boolean.TRUE);
        String nextNode = firstNode;
        while (flags.values().contains(Boolean.FALSE)) {
            Map<String, Integer> nearNodes = nearNodes(nextNode, flags, originalInfo);
            if (nearNodes.isEmpty()) {
                break;
            }
            String finalNextNode = nextNode;
            nearNodes.forEach((node, distance) -> {
                Integer curNodeMin = distanceInfo.get(finalNextNode);
                int min = curNodeMin + distance;
                if (min < distanceInfo.get(node)) {
                    distanceInfo.put(node, min);
                    preNodes.put(node, finalNextNode);
                }
            });
            flags.put(nextNode, Boolean.TRUE);
            nextNode = minNode(flags, distanceInfo);
        }

        List<String> minPath = new LinkedList<>();
        String node = lastNode;
        boolean canReach = true;
        while (true) {
            minPath.add(node);
            node = preNodes.get(node);
            if (node == null) {
                canReach = false;
                System.out.println(String.format("%s-->%s can not reach", firstNode, lastNode));
                break;
            }
            if (node.equals(firstNode)) {
                minPath.add(node);
                break;
            }
        }
        if (canReach) {
            Collections.reverse(minPath);
            System.out.println(String.join("-->", minPath) + " total:" + distanceInfo.get(lastNode));
        }
    }

    private static String minNode(Map<String, Boolean> flags, Map<String, Integer> distanceInfo) {
        Map<String, Integer> temp = new HashMap<>(distanceInfo);
        Set<String> visitedNodes = visitedNodes(flags);
        visitedNodes.forEach(visitedNode -> temp.remove(visitedNode));
        if (temp.isEmpty()) {
            return null;
        }
        Integer min = Collections.min(temp.values());
        for (Map.Entry<String, Integer> entry : temp.entrySet()) {
            if (entry.getValue() == min) {
                return entry.getKey();
            }
        }
        return null;
    }

    private static Map<String, Integer> nearNodes(String
                                                          thisNode, Map<String, Boolean> flags, Map<String, Map<String, Integer>> originalInfo) {
        HashMap<String, Integer> result = new HashMap<>(originalInfo.get(thisNode));
        Set<String> visitedNodes = visitedNodes(flags);
        visitedNodes.forEach(visitedNode -> result.remove(visitedNode));
        return result;
    }

    private static Set<String> visitedNodes(Map<String, Boolean> flags) {
        return flags.entrySet().stream().filter(Map.Entry::getValue).map(Map.Entry::getKey).collect(Collectors.toSet());
    }
}

demo1(图)

在这里插入图片描述
demo2(图)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值