java编写Dijkstra单源最短路径算法

来源:互联网 发布:软件项目沟通机制 编辑:程序博客网 时间:2024/06/05 21:55

Dijkstra单源最短路径算法

此算法用于求出图中的一个源点到其余各点的最短路径,此图必须为带权图且不能有负权值,是否为有向图则没关系

算法思想关键:

设定一个源点s,遍历它的邻边,求出邻边中权值最小的那条边e,获得e另一端点v,则s到v的最短路径必定就是e,因为s到其他点的长度本来就长于e,若还从其他点折回v的话,那长度一定长于e(因此不能有负权边)。然后继续遍历v的邻边,若邻边中最短的边h的另一端点a是之前源点s(即v的上一级节点)遍历过的,则判断h的长度加上e的长度是否小于之前获得的s->a的长度,小于则更新a的相关数据,下面看代码:

类Dijkstra:

public class Dijkstra {private SparseGraph sg;      //有向图private int s;     //源点private int[] distTo;    //存储源点到各点的距离private boolean[] marked;private ArrayList<Edge> from=new ArrayList<Edge>();   //存储指向该顶点的边Edgepublic Dijkstra(SparseGraph sg, int s) {this.sg = sg;this.s = s;distTo=new int[sg.V()];marked=new boolean[sg.V()];for(int i=0;i<sg.V();i++){distTo[i]=0;marked[i]=false;from.add(null);}IndexMinHeap imh=new IndexMinHeap(sg.V());//Dijkstramarked[s]=true;imh.insert(s, distTo[s]);while(!imh.isEmpty()){int v=imh.extractMinIndex();//distTo[v]就是s到v的最短距离marked[v]=true;ArrayList<Edge> arr=sg.getGraph(v);Iterator<Edge> ite=arr.iterator();while(ite.hasNext()){Edge e=ite.next();int w=e.other(v);if(!marked[w]){     //w没有marked即表示s到w的最短路径没有找到if(from.get(w)==null||distTo[v]+e.wt()<distTo[w]){  //from.get(w)==null表示e这条路径没访问过distTo[w]=distTo[v]+e.wt();          //若 distTo[v]+e.wt()<distTo[w],则此操作为松弛操作from.set(w, e);                  //若 distTo[v]+e.wt()<distTo[w],则此操作更新了s到w的最短路径的最后一段if(imh.contain(w))imh.set(w, distTo[w]);elseimh.insert(w, distTo[w]);}}}}}//返回源点到w点的最短路径的权值和public int shortestPathTo(int w){return distTo[w];}//源点到w点是否有路径public boolean hasPathTo(int w){return marked[w];}private void shortestPath(int w,ArrayList<Edge> path){Stack<Edge> s = new Stack<Edge>();Edge e=from.get(w);      //得到指向w点的路径while(e!=null){s.push(e);e=from.get(e.v());}while(!s.isEmpty()){e=s.peek();path.add(e);s.pop();}}public void showPath(int w){assert(w>=0&&w<sg.V());ArrayList<Edge> path=new ArrayList<Edge>();shortestPath(w,path);for(int i=0;i<path.size();i++){System.out.print(path.get(i).v()+"->");if(i==path.size()-1){System.out.print(path.get(i).w());}}}public static void main(String[] args) {int N=10;  //顶点int M=60;   //边SparseGraph sg=new SparseGraph(N,true);for(int i=0;i<M;i++){sg.addEdge(new Random().nextInt(N), new Random().nextInt(N),new Random().nextInt(40)+1);}Dijkstra di=new Dijkstra(sg,3);for(int i=0;i<sg.V();i++){if(di.hasPathTo(i)){di.showPath(i);}System.out.println();}}}
结果如图:


原创粉丝点击