Java实现单源最短路径算法(Dijkstra 算法)

参考:《算法导论》

 

复制代码
@Data
@AllArgsConstructor
public class WeightGraph {
    //节点名,前驱节点,最短路径
    private List<Node<String,String,Integer>> nodes;
    //节点名,连接节点索引,边权重
    private Table<String, Integer, Integer> edgeTable;


    public static void main(String[] args) {
        //构建图
        WeightGraph graph = buildGraph();
        List<Node<String, String, Integer>> nodes = graph.getNodes();
        Table<String, Integer, Integer> edgeTable = graph.getEdgeTable();
        //已知最短路径的节点集合S
        HashSet<String> S = new HashSet<>();
        //优先队列,以最短路径为排序key
        Queue<Node<String,String, Integer>> queue = new PriorityQueue<>(Comparator.comparing(Node::getDistance));
        //节点信息的初始化,v1=0,其他未知都是无穷大
        nodes.forEach(node->{
            if (node.getName().equals("v1")) {
                node.setDistance(0);
            }
        });
        //队列初始化,将所有节点加入队列
        queue.addAll(nodes);
        while (!queue.isEmpty()) {
            //第一个获取的就是v1
            Node<String,String, Integer> nodeU = queue.remove();
            String nodeUName = nodeU.getName();
            S.add(nodeUName);
            Map<Integer, Integer> row = edgeTable.row(nodeUName);
            //对u->v节点进行松弛操作
            //如果v.d大于u.d+w(u,v),则将更小的值更新为v.d
            for (Map.Entry<Integer, Integer> entry : row.entrySet()) {
                Integer nodeVIndex = entry.getKey();
                Node<String, String, Integer> nodeV = nodes.get(nodeVIndex);
                Integer weightUV = entry.getValue();
                if (nodeV.getDistance() > nodeU.getDistance() + weightUV) {
                    nodeV.setDistance(nodeU.getDistance() + weightUV);
                    nodeV.setPre(nodeUName);
                }
            }
        }

        for (Node<String, String, Integer> node : nodes) {
            System.out.println(node.getName()+":"+node.getDistance());
        }

        System.out.println(S);
    }


    /**
     * 初始化图结构
     *
     * @return
     */
    public static WeightGraph buildGraph() {
        List<String> nodes = Lists.newArrayList("v1", "v2", "v3", "v4", "v5", "v6");
        List<Node<String, String, Integer>> nodeList = nodes.stream().map(node -> {
            Node<String, String, Integer> nodeObj = new Node<>();
            nodeObj.setName(node);
            nodeObj.setPre(null);
            nodeObj.setDistance(Integer.MAX_VALUE);
            return nodeObj;
        }).collect(Collectors.toList());

        Table<String, Integer, Integer> edgeTable = HashBasedTable.create();
        edgeTable.put("v1", nodes.indexOf("v2"), 10);
        edgeTable.put("v2", nodes.indexOf("v3"), 7);
        edgeTable.put("v4", nodes.indexOf("v3"), 4);
        edgeTable.put("v4", nodes.indexOf("v5"), 7);
        edgeTable.put("v6", nodes.indexOf("v5"), 1);
        edgeTable.put("v1", nodes.indexOf("v6"), 3);
        edgeTable.put("v6", nodes.indexOf("v2"), 2);
        edgeTable.put("v4", nodes.indexOf("v1"), 3);
        edgeTable.put("v2", nodes.indexOf("v4"), 5);
        edgeTable.put("v6", nodes.indexOf("v4"), 6);

        return new WeightGraph(nodeList,edgeTable);
    }



    /**
     * 节点名,前驱节点,最短路径
     * 也用于存储最终的最短路径数据
     *
     * @param <N>
     * @param <D>
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    static class Node<N,P, D> {
        private N name;
        private P pre;
        private D distance;
    }

}
复制代码

输出:

v1:0
v2:5
v3:12
v4:9
v5:4
v6:3

 

 

posted @   Mars.wang  阅读(381)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示