Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 60953b6

Browse files
committed
added dijkstra, mst
1 parent a8af67d commit 60953b6

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed

‎CCSPiJ/src/chapter4/WeightedGraph.java‎

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package chapter4;
22

33
import java.util.Arrays;
4+
import java.util.Collections;
5+
import java.util.HashMap;
6+
import java.util.LinkedList;
47
import java.util.List;
8+
import java.util.Map;
9+
import java.util.PriorityQueue;
10+
import java.util.function.IntConsumer;
511

612
public class WeightedGraph<V> extends Graph<V, WeightedEdge> {
713

@@ -38,6 +44,138 @@ public String toString() {
3844
return sb.toString();
3945
}
4046

47+
public static double totalWeight(List<WeightedEdge> path) {
48+
return path.stream().mapToDouble(we -> we.weight).sum();
49+
}
50+
51+
// Find the minimum-spanning tree of this graph using Jarnik's algorithm
52+
// *start* is the vertex index to start the search at
53+
public List<WeightedEdge> mst(int start) {
54+
LinkedList<WeightedEdge> result = new LinkedList<>(); // final mst
55+
PriorityQueue<WeightedEdge> pq = new PriorityQueue();
56+
boolean[] visited = new boolean[getVertexCount()]; // where we've been
57+
58+
// this is like a "visit" inner function
59+
IntConsumer visit = index -> {
60+
visited[index] = true; // mark as visited
61+
for (WeightedEdge edge : edgesOf(index)) {
62+
// add all edges coming from here to pq
63+
if (!visited[edge.v]) {
64+
pq.offer(edge);
65+
}
66+
}
67+
};
68+
69+
visit.accept(start); // the first vertex is where everything begins
70+
while (!pq.isEmpty()) { // keep going while there are edges to process
71+
WeightedEdge edge = pq.poll();
72+
if (visited[edge.v]) {
73+
continue; // don't ever revisit
74+
}
75+
// this is the current smallest, so add it to solution
76+
result.add(edge);
77+
visit.accept(edge.v); // visit where this connects
78+
}
79+
80+
return result;
81+
}
82+
83+
public void printWeightedPath(List<WeightedEdge> wp) {
84+
for (WeightedEdge edge : wp) {
85+
System.out.println(vertexAt(edge.u) + " " + edge.weight + "> " + vertexAt(edge.v));
86+
}
87+
System.out.println("Total Weight: " + totalWeight(wp));
88+
}
89+
90+
public static final class DijkstraNode implements Comparable<DijkstraNode> {
91+
public final int vertex;
92+
public final double distance;
93+
94+
public DijkstraNode(int vertex, double distance) {
95+
this.vertex = vertex;
96+
this.distance = distance;
97+
}
98+
99+
@Override
100+
public int compareTo(DijkstraNode other) {
101+
Double mine = distance;
102+
Double theirs = other.distance;
103+
return mine.compareTo(theirs);
104+
}
105+
}
106+
107+
public static final class DijkstraResult {
108+
public final double[] distances;
109+
public final Map<Integer, WeightedEdge> pathMap;
110+
111+
public DijkstraResult(double[] distances, Map<Integer, WeightedEdge> pathMap) {
112+
this.distances = distances;
113+
this.pathMap = pathMap;
114+
}
115+
}
116+
117+
public DijkstraResult dijkstra(V root) {
118+
int first = indexOf(root); // find starting index
119+
// distances are unknown at first
120+
double[] distances = new double[getVertexCount()];
121+
distances[first] = 0; // root's distance to root is 0
122+
boolean[] visited = new boolean[getVertexCount()]; // where we've been
123+
visited[first] = true;
124+
// how we got to each vertex
125+
HashMap<Integer, WeightedEdge> pathMap = new HashMap<>();
126+
PriorityQueue<DijkstraNode> pq = new PriorityQueue<>();
127+
pq.offer(new DijkstraNode(first, 0));
128+
129+
while (!pq.isEmpty()) {
130+
int u = pq.poll().vertex; // explore the next closest vertex
131+
double distU = distances[u]; // should already have seen it
132+
// look at every edge/vertex from the vertex in question
133+
for (WeightedEdge we : edgesOf(u)) {
134+
// the old distance to this vertex
135+
double distV = distances[we.v];
136+
double pathWeight = we.weight + distU;
137+
// new vertex or found shorter path?
138+
if (!visited[we.v] || (distV > pathWeight)) {
139+
visited[we.v] = true;
140+
// update the distance to this vertex
141+
distances[we.v] = pathWeight;
142+
// update the edge on the shortest path to this vertex
143+
pathMap.put(we.v, we);
144+
// explore it in the future
145+
pq.offer(new DijkstraNode(we.v, pathWeight));
146+
}
147+
}
148+
}
149+
150+
return new DijkstraResult(distances, pathMap);
151+
}
152+
153+
// Helper function to get easier access to dijkstra results
154+
public Map<V, Double> distanceArrayToDistanceMap(double[] distances) {
155+
HashMap<V, Double> distanceMap = new HashMap<>();
156+
for (int i = 0; i < distances.length; i++) {
157+
distanceMap.put(vertexAt(i), distances[i]);
158+
}
159+
return distanceMap;
160+
}
161+
162+
// Takes a map of edges to reach each node and return a list of
163+
// edges that goes from *start* to *end*
164+
public static List<WeightedEdge> pathMapToPath(int start, int end, Map<Integer, WeightedEdge> pathMap) {
165+
if (pathMap.size() == 0) {
166+
return List.of();
167+
}
168+
LinkedList<WeightedEdge> path = new LinkedList<>();
169+
WeightedEdge edge = pathMap.get(end);
170+
path.add(edge);
171+
while (edge.u != start) {
172+
edge = pathMap.get(edge.u);
173+
path.add(edge);
174+
}
175+
Collections.reverse(path);
176+
return path;
177+
}
178+
41179
// Test basic Graph construction
42180
public static void main(String[] args) {
43181
// Represents the 15 largest MSAs in the United States
@@ -73,6 +211,23 @@ public static void main(String[] args) {
73211
cityGraph2.addEdge("Philadelphia", "Washington", 123);
74212

75213
System.out.println(cityGraph2);
214+
215+
List<WeightedEdge> mst = cityGraph2.mst(0);
216+
cityGraph2.printWeightedPath(mst);
217+
218+
System.out.println(); // spacing
219+
220+
DijkstraResult dijkstraResult = cityGraph2.dijkstra("Los Angeles");
221+
Map<String, Double> nameDistance = cityGraph2.distanceArrayToDistanceMap(dijkstraResult.distances);
222+
System.out.println("Distances from Los Angeles:");
223+
nameDistance.forEach((name, distance) -> System.out.println(name + " : " + distance));
224+
225+
System.out.println(); // spacing
226+
227+
System.out.println("Shortest path from Los Angeles to Boston:");
228+
List<WeightedEdge> path = pathMapToPath(cityGraph2.indexOf("Los Angeles"), cityGraph2.indexOf("Boston"),
229+
dijkstraResult.pathMap);
230+
cityGraph2.printWeightedPath(path);
76231
}
77232

78233
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /