Skip to content

Commit fb6512e

Browse files
committed
done commenting
1 parent 44ba846 commit fb6512e

File tree

1 file changed

+133
-42
lines changed

1 file changed

+133
-42
lines changed

src/akc170000/MST.java

Lines changed: 133 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
1-
1+
/**
2+
* Long Project 5: Implementation of Minimum Spanning Tree using Prim1, Prim2, Prim3 and Kruskal's algorithm
3+
* @author Axat Chaudhari (akc170000)
4+
* @author Jaiminee Kataria (jxk172330)
5+
* @author Param Parikh (psp170230)
6+
* @author Tej Patel (txp172630)
7+
*/
28
package akc170000;
39

410
import rbk.Graph;
@@ -15,132 +21,204 @@
1521
import java.io.FileNotFoundException;
1622
import java.io.File;
1723

24+
/**
25+
* Class to computer MST on graph G.
26+
* After running MST algorithm, MST is stored in list 'mst' corresponding predecessors are stored in 'parent'
27+
* Weight is MST is stored in 'wmst'
28+
*/
1829
public class MST extends GraphAlgorithm<MST.MSTVertex> {
19-
String algorithm;
20-
public long wmst;
21-
List<Edge> mst;
30+
String algorithm; // which algorithm used to get MST
31+
public long wmst; // total weight of MST
32+
List<Edge> mst; // list containing edges in MST
2233

2334
MST(Graph g) {
2435
super(g, new MSTVertex((Vertex) null));
2536
}
2637

38+
/**
39+
* MSTVertex to store additional properties for vertices of G for computing MST
40+
*/
2741
public static class MSTVertex implements Index, Comparable<MSTVertex>, Factory {
28-
boolean seen; // vertex is visited or not?
29-
Vertex parent; // parent of vertex in MST
30-
int index; // index of vertex in priority queue
31-
int d; // weight of the smallest edge that connects v to some u in G
32-
Vertex vertex; // corresponding vertex
33-
int rank; // rank of node in UNION/FIND data structure
42+
boolean seen; // when v.seen = true: edge e (u,v), where v.d = w(e) is added in MST
43+
Vertex parent; // predecessor vertex in MST. When edge e (u, v) is added to MST, v.parent = u and v.d = w(e)
44+
int index; // index of vertex stored in priority queue
45+
int d; // weight of edge (u,v) that belongs to MST. v.d = w(e)
46+
Vertex vertex; // corresponding graph vertex
47+
int rank; // rank of vertex in UNION/FIND
3448
MSTVertex root; // root of vertex in UNION/FIND
3549
MSTVertex(Vertex u) {
3650
seen = false;
3751
parent = null;
3852
d = Integer.MAX_VALUE;
3953
vertex = u;
40-
root = this;
54+
root = this; // vertex itself is its root node in the beginning
4155
rank = 0;
4256
}
4357

4458
MSTVertex(MSTVertex u) { // for prim2
4559
vertex = u.vertex;
4660
}
4761

62+
/**
63+
* duplicate the MSTVeretx u
64+
* @param u vertex to be copied
65+
* @return new duplicated vertex
66+
*/
4867
public MSTVertex make(Vertex u) { return new MSTVertex(u); }
4968

69+
/**
70+
* set the position of vertex in IndexedPriorityQueue
71+
* @param index index of vertex in IndexedPriorityQueue
72+
*/
5073
public void putIndex(int index) { this.index = index; }
5174

75+
/**
76+
* get the index where vertex is stored in IndexedPriorityQueue
77+
* @return index of vertex
78+
*/
5279
public int getIndex() { return index; }
5380

81+
/**
82+
* used in priority queue to compare weight of two edges e(u,v), e'(u', v') where v.d = w(e) and v'.d = w(e')
83+
* @param other edge e'
84+
* @return 1 if w(e) > w(e'), 0 if w(e) = w(e'), -1 if w(e) < w(e')
85+
*/
5486
public int compareTo(MSTVertex other) {
5587
if(other == null || this.d > other.d) return 1;
5688
else if(this.d < other.d) return -1;
5789
else return 0;
5890
}
5991

92+
/**
93+
* find the root of vertex. point current vertex to root for immediate access in future
94+
* @return root of vertex
95+
*/
6096
public MSTVertex find(){
97+
// recursive call while vertex's root is itself
6198
if(!vertex.equals(root.vertex)){
62-
root = root.find();
99+
root = root.find(); // set direct pointer to its root
63100
}
64101
return root;
65102
}
66103

104+
/**
105+
* union vertex 'rv' with current vertex
106+
* @param rv vertex to union current vertex with
107+
*/
67108
public void union(MSTVertex rv){
109+
// set root of smaller tree as a child of root with bigger tree.
110+
// use rank to determine which tree is bigger
68111
if (rank > rv.rank){
69112
rv.root = this;
70113
}else if(rank < rv.rank){
71114
root = rv;
72-
}else{
115+
}else{ // if both tree has same rank, any one of two root vertices can become new root
73116
rank++;
74117
rv.root = this;
75118
}
76119
}
77120
}
78121

122+
/**
123+
* Kruskal's algorithm:
124+
* - Sort edges is ascending order of weights
125+
* - Add every edge in MST until all vertices in G are covered
126+
* @return total weight of MST
127+
*/
79128
public long kruskal() {
129+
// initialization done in constructor
80130
algorithm = "Kruskal";
81131
Edge[] edgeArray = g.getEdgeArray();
82132
mst = new LinkedList<>();
83133
wmst = 0;
84134
Arrays.sort(edgeArray);
85-
for (Edge e : edgeArray){
86-
MSTVertex ru = get(e.fromVertex()).find();
87-
MSTVertex rv = get(e.toVertex()).find();
88-
if(!ru.vertex.equals(rv.vertex)){
89-
mst.add(e);
90-
ru.union(rv);
135+
for (Edge e : edgeArray){ // for each edge e (u,v) in G
136+
MSTVertex ru = get(e.fromVertex()).find(); // root of u
137+
MSTVertex rv = get(e.toVertex()).find(); // root of v
138+
if(!ru.vertex.equals(rv.vertex)){ // if both are not in same component
139+
mst.add(e); // add e to mst
140+
ru.union(rv); // combine two components
91141
wmst += e.getWeight();
92142
}
93143
}
144+
// at the end #components in UNION/FIND = 1
94145
return wmst;
95146
}
96147

148+
/**
149+
* Prim3 (modification of Prim2)
150+
* using Indexed queue so there are no duplicate vertices in priority queue
151+
* @param s source vertex
152+
* @return total weight of MST
153+
*/
97154
public long prim3(Vertex s) {
98155
algorithm = "indexed heaps";
156+
//initialization
99157
initialize();
100158
get(s).d = 0;
101159
mst = new LinkedList<>();
102160
IndexedHeap<MSTVertex> q = new IndexedHeap<>(g.size());
103161
for (Vertex u : g){
104162
q.add(get(u));
105163
}
164+
106165
while (!q.isEmpty()){
107-
MSTVertex u = q.poll();
108-
u.seen = true;
109-
wmst += u.d;
110-
for (Edge e : g.incident(u.vertex)){
166+
MSTVertex u = q.poll(); //get vertex u representing edge e(v,u) with min weight (v.d)
167+
u.seen = true; // this vertex is processed
168+
wmst += u.d; // update MST weight
169+
170+
for (Edge e : g.incident(u.vertex)){ // every edge e(u,v) outgoing of u
111171
Vertex v = e.otherEnd(u.vertex);
172+
//discard if v already processed or v already represented edge with less weight than e
112173
if(!get(v).seen && e.getWeight() < get(v).d){
174+
// update weight and predecessor
113175
get(v).d = e.getWeight();
114176
get(v).parent = u.vertex;
177+
//update priority queue
115178
q.decreaseKey(get(v));
116179
}
117180
}
118181
}
119182
return wmst;
120183
}
121184

185+
/**
186+
* Prim2 (modification of Prim1)
187+
* - maintain priority queue of vertex.
188+
* - Store only the end vertex v representing edge e(u, v) in priority queue
189+
* - v.d = w(e)
190+
* - v.d is acts as a key in priority queue (see MSTVertex's compareTo(other MSTVertex))
191+
* - There may exist duplicate vertices representing different edges.
192+
* - Only the vertex with min weight is considered in future (this issue is solved in Prim3)
193+
* @param s source vertex
194+
* @return total weight of MST
195+
*/
122196
public long prim2(Vertex s) {
123197
algorithm = "PriorityQueue<Vertex>";
198+
//initialization
124199
initialize();
125200
get(s).d = 0;
126201
mst = new LinkedList<>();
127-
PriorityQueue<MSTVertex> q = new PriorityQueue<>();
202+
PriorityQueue<MSTVertex> q = new PriorityQueue<>(); // priority queue to get remaining min weight edge to add to mst
128203
q.add(get(s));
129204

130205
while (!q.isEmpty()){
131-
MSTVertex u = q.remove();
206+
MSTVertex u = q.remove(); // get edge with min weight. vertex u represents edge e(v,u)
132207
if(!u.seen){
133208
u.seen = true;
134-
wmst+=u.d;
209+
wmst+=u.d; // w(e)
210+
211+
for (Edge e : g.incident(u.vertex)){ // edges (u,v) outgoing of u
212+
Vertex v = e.otherEnd(u.vertex); // other end of edge (u,v)
135213

136-
for (Edge e : g.incident(u.vertex)){
137-
Vertex v = e.otherEnd(u.vertex);
214+
// discard if v is already seen or v already represented edge e' with lesser weight then e
138215
if(!get(v).seen && e.getWeight() < get(v).d){
139-
MSTVertex dupV = new MSTVertex(get(v));
140-
dupV.d = e.getWeight();
141-
dupV.parent = u.vertex;
142-
put(dupV.vertex, dupV).seen = true;
143-
q.add(dupV);
216+
MSTVertex dupV = new MSTVertex(get(v)); // duplicate the old vertex
217+
dupV.d = e.getWeight(); // set new lesser weight of edge
218+
dupV.parent = u.vertex; // now new v represents new edge
219+
get(v).seen = true; // make old vertex seen so that it is never used here again
220+
put(dupV.vertex, dupV); // replace old vertex with new for future access
221+
q.add(dupV); // add to priority queue
144222
}
145223
}
146224

@@ -150,35 +228,48 @@ public long prim2(Vertex s) {
150228
return wmst;
151229
}
152230

231+
/**
232+
* Prim1:
233+
* - maintain priority queue of edges of G
234+
* - remove smallest weight edge from queue and add it to MST if appropriate
235+
* @param s
236+
* @return
237+
*/
153238
public long prim1(Vertex s) {
154239
algorithm = "PriorityQueue<Edge>";
240+
//initialization
155241
initialize();
156242
get(s).seen = true;
157243
mst = new LinkedList<>();
158244
PriorityQueue<Edge> q = new PriorityQueue<>();
159245

246+
//add every edge incident to source to queue
160247
for (Edge e: g.incident(s)){
161248
q.add(e);
162249
}
163250

251+
//while every edge is not processed
164252
while (!q.isEmpty()){
165-
Edge e = q.remove();
166-
Vertex v = get(e.fromVertex()).seen ? e.toVertex() : e.fromVertex();
167-
if(get(v).seen) continue;
253+
Edge e = q.remove(); // extract min weight edge e(u,v) with u.seen = true
254+
Vertex v = get(e.fromVertex()).seen ? e.toVertex() : e.fromVertex(); // get v from e(u,v)
255+
if(get(v).seen) continue; // discard if other end is also processed
168256

169-
get(v).seen = true;
170-
get(v).parent = e.otherEnd(v);
171-
wmst += e.getWeight();
257+
get(v).seen = true; // this vertex is processed now
258+
get(v).parent = e.otherEnd(v); // set its predecessor as u
259+
wmst += e.getWeight(); // update weight
172260

173-
for (Edge e2 : g.incident(v)){
174-
if (!get(e2.otherEnd(v)).seen){
175-
q.add(e2);
261+
for (Edge e1 : g.incident(v)){ // for every outgoing edge e1(v, u)
262+
if (!get(e1.otherEnd(v)).seen){ // if u is not processed, meaning edge (v,u) is not processed, add to queue
263+
q.add(e1);
176264
}
177265
}
178266
}
179267
return wmst;
180268
}
181269

270+
/**
271+
* Initialization process for all prim algorithms
272+
*/
182273
void initialize(){
183274
for (Vertex u: g){
184275
get(u).seen = false;

0 commit comments

Comments
 (0)