Dijkstra

 

package com.example.demo.code90;


import com.example.demo.code10.queue.Queue;
import com.example.demo.code80.DirectedEdge;
import com.example.demo.code80.EdgeWeightedDigraph;
import com.example.demo.study.tree.youxianqueue.IndexMinPriorityQueue;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
 * @author ming
 * @create 2022/6/20
 * @description:
 */
public class DijkstraSP  {
    //索引代表顶点,值代表从顶点s到当前顶点的最短路径上的最后一条边
    private DirectedEdge[] edgeTo;
    //索引代表顶点,值从顶点s到当前顶点的最短路径的总权重
    private double[] disTo;
    //存放树中顶点与非树中顶点之间的有效横切边
    private IndexMinPriorityQueue<Double> pq;
    //根据一副加权有向图G和顶点s,创建一个计算顶点为s的最短路径的树对象


    public DijkstraSP(EdgeWeightedDigraph G, int s) {
        this.edgeTo = new DirectedEdge[G.v()];
        //初始化disTo
        this.disTo = new double[G.v()];
        for (int i = 0; i < disTo.length; i++) {
            disTo[i] = Double.MAX_VALUE;
        }
        this.pq = new IndexMinPriorityQueue(G.v());
        //找到图G中以顶点s为起点的最短路径树
        
        //默认让顶点s进入到最短路径树中
        disTo[s] = 0.0;
        pq.insert(s,0.0);
        //遍历pq
        while(!pq.isEmpty()){
            relax(G,pq.delMin());
        }
    }

    private void relax(EdgeWeightedDigraph g, int v) {
        for (DirectedEdge edge : g.adj(v)) {
            //获取该边的终点w
            int w = edge.to();
            //判断从起点s到顶点w是否需要先从顶点s到顶点v,然后再有顶点v到顶点w
            if(disTo[v]+edge.weight()<disTo(w)){
                disTo[w] = disTo[v]+edge.weight();
                edgeTo[w] = edge;
                //判断pq是否已经存在w,如果存在更新权重,如果不存在直接添加
                if(pq.contains(w)){
                    pq.changeItem(w,disTo(w));
                }else{
                    pq.insert(w,disTo(w));
                }
            }
        }
    }
    //获取从顶点s到顶点v的最短路径的总权重
    private double disTo(int v) {
        return disTo[v];
    }
    //判断从顶点s到顶点v是否可达
    public boolean hasPathTo(int v){
        return disTo[v]<Double.MAX_VALUE;
    }
    //查询从起点s到顶点v的最短路径所有的边
    public Queue<DirectedEdge> pathTo(int v){
        if(!hasPathTo(v)){
            return null;
        }
        //创建队列对象
        Queue<DirectedEdge> allEdges = new Queue<>();
        while(true){
            DirectedEdge e = edgeTo[v];
            if(e==null){
                break;
            }
            allEdges.enqueue(e);
            v = e.from();
        }
        return allEdges;
    }

    public static void main(String[] args) throws Exception {
        /**
         * 8
         * 15
         * 4 5 0.35
         * 5 4 0.35
         * 4 7 0.37
         * 5 7 0.28
         * 7 5 0.28
         * 5 1 0.32
         * 0 4 0.38
         * 0 2 0.26
         * 7 3 0.39
         * 1 3 0.29
         * 2 7 0.34
         * 6 2 0.40
         * 3 6 0.52
         * 6 0 0.58
         * 6 4 0.93
         */
        //创建一副加权有向图
        BufferedReader reader = new BufferedReader(new InputStreamReader(DijkstraSP.class.getClassLoader().getResourceAsStream("min_route_test.txt")));
        int total = Integer.parseInt(reader.readLine());
        EdgeWeightedDigraph G = new EdgeWeightedDigraph(total);
        int edgeNumber = Integer.parseInt(reader.readLine());
        for (int i = 0; i < edgeNumber; i++) {
            String[] line = reader.readLine().split(" ");
            int v = Integer.parseInt(line[0]);
            int w = Integer.parseInt(line[1]);
            double weight = Double.parseDouble(line[2]);
            DirectedEdge e = new DirectedEdge(v, w, weight);
            G.addEdge(e);
        }
        //创建DijksSp对象,查找最短路径树
        DijkstraSP dijstraSp = new DijkstraSP(G, 0);
        //查找最短路径  查找0-6的最短路径
        Queue<DirectedEdge> directedEdges = dijstraSp.pathTo(6);
        //遍历打印
        for (DirectedEdge e : directedEdges) {
            System.out.println(e.from()+"->"+e.to()+"::"+e.weight());
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值