图之单源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.

posted @ 2017-04-07 09:26  日青天  阅读(1567)  评论(0编辑  收藏  举报