4.Dijkstra单点最短路径算法 迪杰斯特拉

Dijkstra最短路径树   VS  Prim最小生成树

具象表现为:

1)二者都是通过添加边负的方式构造树

2)prim算法每一步添加的是离树最近的非树顶点

3)Dijkstra算法每一步添加的是离起点s最近的非树顶点


Dijkstra最短路径树解决的问题:加权有向图非负权重情况下,给定起点s和任意顶点v的最短路径问题

若想要实现任意两点最短路径,只需要把图中的所有顶点作为起点都计算一遍即可,比如构建DijkstraSP [] dijkstraSPs对象数组,将每个顶点都作为起点计算。 



using UnityEngine;
using System.Collections;
using System.Collections.Generic;


public class DijkstraSP : MonoBehaviour {


    public TextAsset Graph;
    void Start()
    {
        double a = double.PositiveInfinity;
        double b = (double.PositiveInfinity + 10.0);
        print(a > b);
        print(a < b);
        print(a == b);


        EdgeWeightedDigraph G = new EdgeWeightedDigraph(Graph);
        int s = 0;


        // compute shortest paths
        DijkstraSP sp = new DijkstraSP(G, s);




        // print shortest path
        for (int t = 0; t < G.V(); t++)
        {
            if (sp.hasPathTo(t))
            {
                string str = s + " to " + t + "  Distance=" + sp.DistTo(t);
                
                foreach (DirectedEdge e in sp.PathTo(t))
                {
                    str+=(e + "\t");
                }
                print(str);
            }
            else
            {
                print(s+" to "+ t+"         no path\n");
            }
        }
    }


    private double[] distTo;          // distTo[v] = distance  of shortest s->v path
    private DirectedEdge[] edgeTo;    // edgeTo[v] = last edge on shortest s->v path
    private IndexMinPQ<double> pq;    // priority queue of vertices


   
    public DijkstraSP(EdgeWeightedDigraph G, int s)
    {
        foreach (DirectedEdge e in G.edges())
        {
            if (e.Weight() < 0)
                throw new System.Exception("edge " + e + " has negative weight");
        }


        distTo = new double[G.V()];
        edgeTo = new DirectedEdge[G.V()];


        validateVertex(s);


        for (int v = 0; v < G.V(); v++)
            distTo[v] = double.PositiveInfinity;
        distTo[s] = 0.0;




        // relax vertices in order of distance from s
        IndexMinPQComparer comparator =new IndexMinPQComparer();
        pq = new IndexMinPQ<double>(G.V(),(Comparer<double>)comparator);
        pq.insert(s, distTo[s]);
        while (!pq.isEmpty())
        {
            int v = pq.delMin();
            foreach (DirectedEdge e in G.Adj(v))
                relax(e);
        }


       
    }


    // relax edge e and update pq if changed
    private void relax(DirectedEdge e)
    {
        int v = e.from(), w = e.to();
        if (distTo[w] > distTo[v] + e.Weight())
        {
            distTo[w] = distTo[v] + e.Weight();
            edgeTo[w] = e;
            if (pq.contains(w)) pq.decreaseKey(w, distTo[w]);
            else pq.insert(w, distTo[w]);
        }
    }


    private void relax(EdgeWeightedDigraph G,int v)
    {
        foreach (DirectedEdge e in G.Adj(v))
        {
            int  w = e.to();
            if (distTo[w] > distTo[v] + e.Weight())
            {
                distTo[w] = distTo[v] + e.Weight();
                edgeTo[w] = e;
            }


        }
       
    }




    //起点s到v的距离,如果路径不存在,则为无穷大
    public double DistTo(int v)
    {
        validateVertex(v);
        return distTo[v];
    }


   


    //是否存在s到v的路径
    public bool hasPathTo(int v)
    {
        validateVertex(v);
        return distTo[v] < double.PositiveInfinity;
    }


  //起点s到终点v的最短有向路径,不存在则返回null
    public Stack<DirectedEdge> PathTo(int v)
    {
        validateVertex(v);
        if (!hasPathTo(v)) return null;
        Stack<DirectedEdge> path = new Stack<DirectedEdge>();
        for (DirectedEdge e = edgeTo[v]; e != null; e = edgeTo[e.from()])
        {
            path.push(e);
        }
        return path;
    }




    private bool Check(EdgeWeightedDigraph G, int s)
    {


        // check that edge weights are nonnegative
        foreach (DirectedEdge e in G.edges())
        {
            if (e.Weight() < 0)
            {
                throw new System.Exception("negative edge weight detected");
                return false;
            }
        }


        // check that distTo[v] and edgeTo[v] are consistent
        if (distTo[s] != 0.0 || edgeTo[s] != null)
        {
            throw new System.Exception("distTo[s] and edgeTo[s] inconsistent");
            return false;
        }
        for (int v = 0; v < G.V(); v++)
        {
            if (v == s) continue;
            if (edgeTo[v] == null && distTo[v] != double.PositiveInfinity)
            {
                throw new System.Exception("distTo[] and edgeTo[] inconsistent");
                return false;
            }
        }


        // check that all edges e = v->w satisfy distTo[w] <= distTo[v] + e.weight()
        for (int v = 0; v < G.V(); v++)
        {
            foreach (DirectedEdge e in G.Adj(v))
            {
                int w = e.to();
                if (distTo[v] + e.Weight() < distTo[w])
                {
                    throw new System.Exception("edge " + e + " not relaxed");
                    return false;
                }
            }
        }


        // check that all edges e = v->w on SPT satisfy distTo[w] == distTo[v] + e.weight()
        for (int w = 0; w < G.V(); w++)
        {
            if (edgeTo[w] == null) continue;
            DirectedEdge e = edgeTo[w];
            int v = e.from();
            if (w != e.to()) return false;
            if (distTo[v] + e.Weight() != distTo[w])
            {
                throw new System.Exception("edge " + e + " on shortest path not tight");
                return false;
            }
        }
        return true;
    }


    // throw an IllegalArgumentException unless {@code 0 <= v < V}
    private void validateVertex(int v)
    {
        int V = distTo.Length;
        if (v < 0 || v >= V)
            throw new System.Exception("vertex " + v + " is not between 0 and " + (V - 1));
    }


   
   
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值