图之单源Dijkstra算法、带负权值最短路径算法
1、图类基本组成
存储在邻接表中的基本项
1 /** 2 * Represents an edge in the graph 3 * 4 */ 5 class Edge implements Comparable<Edge> { 6 public Vertex dest; //Second vertex in Edge 7 public double cost; //Edge cost 8 9 public Edge(Vertex d, double c) { 10 dest = d; 11 cost = c; 12 } 13 14 @Override 15 public int compareTo(Edge o) { 16 double otherCost = o.cost; 17 return cost < otherCost ? -1 : cost > otherCost ? 1 : 0; 18 } 19 20 @Override 21 public String toString() { 22 return "Edge{" + "dest=" + dest + ", cost=" + cost + '}'; 23 } 24 }
存储每个顶点信息
1 /** 2 * Represents a vertex in the graph 3 */ 4 class Vertex { 5 public String name; 6 public List<Edge> adj;//Adjacent vertices 7 public double dist; 8 public Vertex prev; 9 public int scratch;//Extra variable used in algorithm 10 11 public Vertex(String name) { 12 this.name = name; 13 adj = new LinkedList<Edge>(); 14 reset(); 15 } 16 17 public void reset() { 18 dist = Graph.INFINITY; 19 prev = null; 20 scratch = 0; 21 } 22 23 @Override 24 public String toString() { 25 return "Vertex{" + "name='" + name + '\'' + ", prev=" + prev + ", adj=" + adj + ", dist=" + dist + '}'; 26 } 27 }
图类的框架
1 import java.util.*; 2 3 /** 4 * Created by Vanguard on 2017/4/6. 5 */ 6 public class Graph { 7 public static final double INFINITY = Double.MAX_VALUE; 8 private Map<String, Vertex> vertexMap = new HashMap<String, Vertex>(); 9 10 public void addEdge(String sourceName, String destName, double cost) { 11 Vertex v = getVertex(sourceName); 12 Vertex w = getVertex(destName); 13 v.adj.add(new Edge(w, cost)); 14 } 15 16 /** 17 * 通过查询图的表,打印最短路径 18 * 19 * @param destName 20 */ 21 public void printPath(String destName) { 22 Vertex w = vertexMap.get(destName); 23 if (w == null) { 24 System.out.println("NoSuchElementException"); 25 return; 26 } else if (w.dist == INFINITY) { 27 System.out.println(destName + " is unreachable."); 28 } else { 29 System.out.print("(Cost is: " + w.dist + ") "); 30 printPath(w); 31 System.out.println(); 32 } 33 } 34 35 private void printPath(Vertex dest) { 36 if (dest.prev != null) { 37 printPath(dest.prev); 38 System.out.print(" --> "); 39 } 40 System.out.print(dest.name); 41 } 42 43 44 private Vertex getVertex(String vertexName) { 45 Vertex v = vertexMap.get(vertexName); 46 if (v == null) { //create if not exist. 47 v = new Vertex(vertexName); 48 vertexMap.put(vertexName, v); 49 } 50 return v; 51 } 52 53 private void clearAll() { 54 for (Vertex v : vertexMap.values()) { 55 v.reset(); 56 } 57 } 58 }
2、最短路径算法
广度优先搜索
1 /** 2 * Single-source unweighted shortest-path algorithm. 3 * 无权单源最短路径算法——广度优先搜索 4 * 5 * @param startName 6 */ 7 public void unweighted(String startName) { 8 clearAll(); 9 Vertex start = vertexMap.get(startName); 10 if (start == null) { 11 throw new NoSuchElementException("Start vertex not fond."); 12 } 13 Queue<Vertex> q = new LinkedList<Vertex>(); 14 q.add(start); 15 start.dist = 0; 16 while (!q.isEmpty()) { 17 Vertex v = q.remove(); 18 for (Edge e : v.adj) { 19 Vertex w = e.dest; 20 if (w.dist == INFINITY) { 21 w.dist = v.dist + 1; 22 w.prev = v; 23 q.add(w); 24 } 25 } 26 } 27 }
Dijstra算法
1 /** 2 * Single-source unweighted shortest-path algorithm. 3 * 无权单源最短路径算法——广度优先搜索 4 * 5 * @param startName 6 */ 7 public void unweighted(String startName) { 8 clearAll(); 9 Vertex start = vertexMap.get(startName); 10 if (start == null) { 11 throw new NoSuchElementException("Start vertex not fond."); 12 } 13 Queue<Vertex> q = new LinkedList<Vertex>(); 14 q.add(start); 15 start.dist = 0; 16 while (!q.isEmpty()) { 17 Vertex v = q.remove(); 18 for (Edge e : v.adj) { 19 Vertex w = e.dest; 20 if (w.dist == INFINITY) { 21 w.dist = v.dist + 1; 22 w.prev = v; 23 q.add(w); 24 } 25 } 26 } 27 }
带负权值得最短路径算法
1 /** 2 * Single-source negative-weighted shortest-path algorithm. 3 * 带负权值得最短路径算法 4 * 5 * @param startName 6 */ 7 public void negative(String startName) { 8 clearAll(); 9 10 Vertex start = vertexMap.get(startName); 11 if (start == null) { 12 throw new NoSuchElementException("Start vertex not fond."); 13 } 14 Queue<Vertex> q = new LinkedList<>(); 15 q.add(start); 16 start.dist = 0; 17 start.scratch++; 18 while (!q.isEmpty()) { 19 Vertex v = q.remove(); 20 if (v.scratch++ > 2 * vertexMap.size()) { 21 System.out.println("Negative cycle detected."); 22 } 23 for (Edge e : v.adj) { 24 Vertex w = e.dest; 25 double costvw = e.cost; 26 if (w.dist > v.dist + costvw) { 27 w.dist = v.dist + costvw; 28 w.prev = v; 29 //Enqueue only if not already on the queue 30 if (w.scratch++ % 2 == 0) 31 q.add(w); 32 else 33 w.scratch--; 34 } 35 } 36 37 } 38 }
THE END.