转载自:http://www.2cto.com/kf/201304/200733.html
看得略有点久,所以加了注释上去
package test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.PriorityQueue; //首先,我们需要先定义一个边界值的类Edge //接着,我们需要定义一个顶点的类 //然后,我们根据顶点去遍历边界值,每次更新 //当所有的顶点都包括进去后,那自然也就得到最短路径了 public class Dijkstra { public static Map<String, Vertex> vertexMap = new HashMap<String, Vertex>(); public static void main(String[] args) { // TODO Auto-generated method stub Vertex v1 = new Vertex("v1"); Vertex v2 = new Vertex("v2"); Vertex v3 = new Vertex("v3"); Vertex v4 = new Vertex("v4"); Vertex v5 = new Vertex("v5"); List<Edge> e1l = v1.adj; List<Edge> e2l = v2.adj; List<Edge> e3l = v3.adj; List<Edge> e4l = v4.adj; // 因为V5这个点并没有到其它任何一点,所以不加入 // List<Edge> e5l = v5.adj; Edge e12 = new Edge(v2, 10); Edge e14 = new Edge(v4, 30); Edge e15 = new Edge(v5, 100); e1l.add(e14); e1l.add(e15); e1l.add(e12); Edge e23 = new Edge(v3, 50); e2l.add(e23); Edge e35 = new Edge(v5, 10); e3l.add(e35); Edge e43 = new Edge(v3, 20); Edge e45 = new Edge(v5, 60); e4l.add(e43); e4l.add(e45); /* * 以上代码构建有向图 v1---->v5:100 v1----->V4:30 v1------>V2:10 * * V2------>V3:50 V3------->V5:10 v4------->V3:20 v4------->V5:60 */ vertexMap.put("v1", v1); vertexMap.put("v2", v2); vertexMap.put("v3", v3); vertexMap.put("v4", v4); vertexMap.put("v5", v5); dijkstral("v1", "v5"); } // 每一次迭代,会以整个点来更新图,如果更新,就把点加进去 // 问题在于找的那个点,是否有什么不对 // c代表整个的路径长度 public static void dijkstral(final String startName, final String endName) { //该队列以权值升序排列,因为Vertex实现Comparable接口 PriorityQueue<Vertex> queue = new PriorityQueue<Vertex>(); Vertex start = vertexMap.get(startName); start.dist = 0; for (Vertex v : vertexMap.values()) queue.add(v); int seenNum = 0; while (!queue.isEmpty() && seenNum < vertexMap.size()) { Vertex v = queue.remove(); if (v.name.equals(endName)) { // 恰好是自己要找的那个点 System.out.println(startName + "---->" + v.name + "距离是: " + v.dist); System.out.println(getPreNames(v)); break; } // 如果这个顶点有被访问过,那么我们跳过这一次的执行 if (v.visited) continue; v.visited = true;// 已经被访问过了,所以设置为true seenNum++; // 每次遍历,如果找到还有更小的点,那么就把路径更新上去 for (Edge e : v.adj) { Vertex w = e.dest; double v_to_w = e.cost; if (w.dist > v.dist + v_to_w) { w.dist = v.dist + v_to_w; w.prev = v; queue.remove(w); queue.add(w); } } } } // dest代表着到哪个点 // cost代表着到那个点的距离 static class Edge { public Vertex dest; public double cost; public Edge(Vertex d, double c) { this.dest = d; this.cost = c; } } // name:顶点的名字 // adj:分别到哪些个点的list // dist:最短的距离 // prev:表示哪个点到它这 // visited:是否有被访问过 static class Vertex implements Comparable<Vertex>{ public String name; public List<Edge> adj; public double dist; public Vertex prev; public boolean visited; public Vertex(String nm) { this.name = nm; adj = new ArrayList<Edge>(); reset(); } public void reset() { visited = false; dist = 99999; } @Override public int compareTo(Vertex o) { // TODO Auto-generated method stub double c = o.dist; return dist < c ? -1:dist > c ? 1:0; } } // 得到最短路径的路线,并整理好吰,返回 public static String getPreNames(Vertex v) { String routeEndName = v.name; StringBuilder sb = new StringBuilder(); // 先从终点起,把所有的点都弄出来 while (v.prev != null) { sb.append(v.prev.name + ","); v = v.prev; } String reverseRoute = routeEndName + "," + sb.toString(); String[] reverseArray = reverseRoute.split(","); StringBuilder route = new StringBuilder(); // 再调整顺序,返回 for (int i = 0; i < reverseArray.length; i++) { route.append(reverseArray[reverseArray.length - 1 - i]); route.append(","); } return route.substring(0, route.length() - 1); } }