-
Notifications
You must be signed in to change notification settings - Fork 0
/
Path.java
116 lines (101 loc) · 4.19 KB
/
Path.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package submit;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import graph.Edge;
import graph.Node;
/** This class contains the solution to A7, shortest-path algorithm, <br>
* and other methods for an undirected graph. */
public class Path {
/** = the shortest path from node v to node end <br>
* ---or the empty list if a path does not exist. <br>
* Note: The empty list is a list with 0 elements ---it is not "null". */
public static List<Node> shortestPath(Node v, Node end) {
// Contains an entry for each node in the frontier set. The priority of
// a node is the length of the shortest known path from v to the node
// using only settled nodes except for the last node, which is in F.
var F= new Heap<Node>(true);
// Contains an entry for each node in the frontier and settled sets, giving
// its shortest path length known so far and backpointer.
var SandF= new HashMap<Node, Info>();
F.insert(v, 0);
SandF.put(v, new Info(0, null));
// inv: The invariant of the abstract algorithm AND
// . . .The def of SandF given above
while (F.size() != 0) {
var f= F.poll();
if (f == end) return pathToEnd(SandF, end);
var fInfo= SandF.get(f);
for (Edge e : f.exits()) {
var w= e.other(f);
var wDist= fInfo.dist + e.length;
var wInfo= SandF.get(w);
if (wInfo == null) { // w not in S or F
F.insert(w, wDist);
SandF.put(w, new Info(wDist, f));
} else {
if (wDist < wInfo.dist) {
F.changePriority(w, wDist);
wInfo.dist= wDist;
wInfo.bkptr= f;
}
}
}
}
// no path from v to end. Do not change this
return new LinkedList<>();
}
/** An instance contains info about a node: <br>
* the known shortest distance of this node from the start node and <br>
* its backpointer: the previous node on a shortest path <br>
* from the first node to this node (null for the start node). */
private static class Info {
/** shortest known distance from the start node to this one. */
private int dist;
/** backpointer on path (with shortest known distance) from <br>
* start node to this one */
private Node bkptr;
/** Constructor: an instance with dist d from the start node and<br>
* backpointer p. */
private Info(int d, Node p) {
dist= d; // Distance from start node to this one.
bkptr= p; // Backpointer on the path (null if start node)
}
/** = a representation of this instance. */
@Override
public String toString() {
return "dist " + dist + ", bckptr " + bkptr;
}
}
/** = the path from the start node to node end.<br>
* Precondition: SandF contains all the necessary information about<br>
* ............. the path. */
public static List<Node> pathToEnd(HashMap<Node, Info> SandF, Node end) {
List<Node> path= new LinkedList<>();
var p= end;
// invariant: All the nodes from p's successor to node
// . . . . . .end are in path, in reverse order.
while (p != null) {
path.add(0, p);
p= SandF.get(p).bkptr;
}
return path;
}
/** = the sum of the weights of the edges on path p. <br>
* Precondition: p contains at least 1 node. <br>
* If 1 node, it's a path of length 0, i.e. with no edges. */
public static int pathSum(List<Node> p) {
synchronized (p) {
Node w= null;
var sum= 0;
// invariant: if w is null, n is the start node of the path.<br>
// .......... if w is not null, w is the predecessor of n on the path.
// .......... sum = sum of weights on edges from first node to v
for (Node n : p) {
if (w != null) sum= sum + w.edge(n).length;
w= n;
}
return sum;
}
}
}