Mercurial > hg > STI-GWT
comparison war/scripts/sti/kruskal.js @ 3:cf06b77a8bbd
Committed branch of the e4D repos sti-gwt branch 16384.
git-svn-id: http://dev.dariah.eu/svn/repos/eu.dariah.de/ap1/sti-gwt-dariah-geobrowser@36 f2b5be40-def6-11e0-8a09-b3c1cc336c6b
author | StefanFunk <StefanFunk@f2b5be40-def6-11e0-8a09-b3c1cc336c6b> |
---|---|
date | Tue, 17 Jul 2012 13:34:40 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:2897af43ccc6 | 3:cf06b77a8bbd |
---|---|
1 var infinity = 100000000000; // !!! beware, not allowable for many applications | |
2 | |
3 function Edge2(a, b, w) { this.v1=a; this.v2=b; this.wt=w; } | |
4 | |
5 function setEdgeAdjMatrix(i, j, w) | |
6 { if(j > i) { var t=i; i=j; j=t; }//swap so that i >= j | |
7 this.matrix[i][j] = w; | |
8 } | |
9 | |
10 | |
11 function randomAdjMatrix(pr) // allocate random edges with probability 'pr'; LA | |
12 { var i, j; | |
13 for(i=0; i < this.Vertices; i++) | |
14 { for(j=0; j < i; j++) | |
15 { if(Math.random() <= pr)//LAllison, roll dice | |
16 this.setEdge(i, j, 1+Math.round(Math.random()*8)); // wt in [1..9] | |
17 } } }//randomAdjMatrix | |
18 | |
19 | |
20 function edgeWeightAdjMatrix(i,j) | |
21 { return i >= j ? this.matrix[i][j] : this.matrix[j][i]; } | |
22 | |
23 function adjacentAdjMatrix(i, j) | |
24 { return this.edgeWeight(i,j) < infinity; } | |
25 | |
26 | |
27 function AdjMatrix(Vrtcs) // constructor for a Graph as an Adjacency Matrix | |
28 { this.Vertices = Vrtcs; // Vertices [0..Vrtcs-1] | |
29 this.edgeWeight = edgeWeightAdjMatrix; // These functions | |
30 this.adjacent = adjacentAdjMatrix; // and values | |
31 this.random = randomAdjMatrix; | |
32 this.setEdge = setEdgeAdjMatrix; | |
33 | |
34 this.matrix = new Array(Vrtcs); // the Graph representation... | |
35 var i, j; | |
36 for(i=0; i < Vrtcs; i++) // undirected graph so... | |
37 { this.matrix[i] = new Array(i+1); // symmetric => triangular !!! | |
38 for(j=0; j <= i; j++) | |
39 this.setEdge(i, j, infinity); // no edges, yet | |
40 } | |
41 }//AdjMatrix | |
42 | |
43 //----------------------------------------------------------------------------- | |
44 | |
45 function AdjListCell(vert, w, next) | |
46 { this.v = vert; this.wt = w; this.tl = next; } | |
47 | |
48 function AdjListFromAdjMatrix(GbyMatrix) | |
49 { var v1, v2; | |
50 this.Vertices = GbyMatrix.Vertices; | |
51 | |
52 for(v1=0; v1 < this.Vertices; v1++) | |
53 { this.vertex[v1] = null; // clear | |
54 | |
55 for(v2=this.Vertices-1; v2 >= v1; v2--) // v1 <= v2 | |
56 { if(GbyMatrix.adjacent(v1, v2)) | |
57 { var wt = GbyMatrix.edgeWeight(v1, v2); | |
58 this.vertex[v1] = new AdjListCell(v2, wt, this.vertex[v1]); | |
59 } | |
60 } | |
61 } | |
62 }//AdjListFromAdjMatrix | |
63 | |
64 function AdjList(Vrtcs) // Constructor for a Graph by Adjacency Lists C | |
65 { this.Vertices = Vrtcs; // o | |
66 this.fromAdjMatrix = AdjListFromAdjMatrix; // m | |
67 // p | |
68 this.vertex = new Array(Vrtcs); // set up the adjacency lists . | |
69 var i; // S | |
70 for(i=0; i < Vrtcs; i++) this.vertex[i]=null; // c | |
71 }//AdjList i | |
72 | |
73 //----------------------------------------------------------------------------- | |
74 | |
75 function Prim(G) | |
76 // Post: T[] is a minimum spanning tree of G and | |
77 // T[i-1] is the edge linking Vertex i into the tree | |
78 // Time complexity is O(|V|**2) | |
79 { var T = new Array(G.Vertices-1); | |
80 var i; | |
81 var done = new Array(G.Vertices); | |
82 | |
83 done[0] = true; // initially T=<{0},{ }> | |
84 for(i = 1; i < G.Vertices; i++) | |
85 { T[i-1] = new Edge2(0, i, G.edgeWeight(0,i)); | |
86 done[i]=false; | |
87 } | |
88 | |
89 var dontCare; | |
90 for(dontCare = 1; dontCare < G.Vertices; dontCare++)// |V|-1 times... L | |
91 // Invariant: T is a min' spanning sub-Tree of vertices in done A | |
92 { // find the undone vertex that is closest to the Spanning (sub-)Tree l | |
93 var minDist = infinity, closest = -1; // l | |
94 for(i = 1; i < G.Vertices; i++) // i | |
95 if(! done[i] && T[i-1].wt <= minDist) // s | |
96 { minDist = T[i-1].wt; closest = i; } // o | |
97 done[closest] = true; // n | |
98 | |
99 for(i=1; i < G.Vertices; i++) // recompute undone proximities to T | |
100 if(! done[i]) | |
101 { var Gci = G.edgeWeight(closest, i); | |
102 if(Gci < T[i-1].wt) | |
103 { T[i-1].wt = Gci; | |
104 T[i-1].v1 = closest; | |
105 } } } | |
106 | |
107 return T; | |
108 }//Prim | |
109 | |
110 // ---------------------------------------------------------------------------- | |
111 | |
112 function PartitionMerge(s1, s2) | |
113 // merge the smaller of subsets s1 and s2 into the larger of them. M | |
114 { var drop, keep; // o | |
115 if(this.subset[s1].nElts < this.subset[s2].nElts) // drop the smaller n | |
116 { drop=s1; keep=s2; } // a | |
117 else // s | |
118 { drop=s2; keep=s1; } // h | |
119 | |
120 var dropElt = this.subset[drop].firstElt; // each element in smaller subset | |
121 var done=false; | |
122 while(! done) | |
123 { this.elt[dropElt].setNumber = keep; // move the element to larger subset | |
124 if( this.elt[dropElt].nextElt < 0) | |
125 done = true; | |
126 else | |
127 dropElt = this.elt[dropElt].nextElt; | |
128 }//end while | |
129 | |
130 this.elt[dropElt].nextElt = this.subset[keep].firstElt; // join lists | |
131 this.subset[keep].firstElt = this.subset[drop].firstElt; | |
132 this.subset[keep].nElts += this.subset[drop].nElts; | |
133 | |
134 this.subset[drop].firstElt = -1; // clear smaller subset | |
135 this.subset[drop].nElts = 0; | |
136 | |
137 this.size --; // one less subset in the partition | |
138 }//PartitionMerge | |
139 | |
140 | |
141 function PartitionEltCell(sn, nxt) { this.setNumber = sn; this.nextElt = nxt; } | |
142 | |
143 function PartitionSetCell(ne, fst) { this.nElts = ne; this.firstElt = fst; } | |
144 | |
145 | |
146 function PartitionSingletons() // make {{0}, {1}, {2}, ...} | |
147 { var i; | |
148 this.size = (this.elt).length; // # of subsets in the partition | |
149 for(i=0; i < this.size; i++) | |
150 { this.elt[i] = new PartitionEltCell(i, -1); | |
151 this.subset[i] = new PartitionSetCell(1, i); // i.e. i is in {i} | |
152 } } | |
153 | |
154 | |
155 function Partition(N) // A | |
156 { this.elt = new Array(N); // elements -> subsets l | |
157 this.subset = new Array(N); // subsets -> elements l | |
158 // i | |
159 this.singletons = PartitionSingletons; // s | |
160 this.merge = PartitionMerge; // o | |
161 }//Partition constructor n | |
162 | |
163 | |
164 function upHeap(e) // see PriorityQ L | |
165 // add e to the (smallest on top) heap, arr[1..size] A | |
166 // PRE: arr[1..size] is a (smallest at top) heap / priority Q l | |
167 // POST: arr[1..size] is a (bigger) heap, with e added l | |
168 { this.size++; // i | |
169 var child = this.size, parent; // s | |
170 while(child > 1)//i.e. not top of heap // o | |
171 { parent = Math.floor(child / 2); // n | |
172 | |
173 if(this.arr[parent].wt > e.wt) | |
174 this.arr[child] = this.arr[parent]; // move parent down | |
175 else | |
176 break; // found a place for e | |
177 child = parent; | |
178 } | |
179 | |
180 // either child==1, i.e. parentless, or parent is less than or eq to e | |
181 this.arr[child] = e; | |
182 }//upHeap, L.Allison, Comp Sci and Software Engineering, Monash University | |
183 | |
184 | |
185 function downHeap(e) | |
186 // add e to the (smallest on top) heap, arr[2..size] | |
187 // PRE: arr[2..size] is a heap | |
188 // POST: arr[1..size] is a heap | |
189 { var parent = 1, child; // A | |
190 while(2*parent <= this.size) // U | |
191 { child = 2*parent; // left child is 2*parent, right is 2*parent+1 // S | |
192 // T | |
193 if(child < this.size && this.arr[child+1].wt < this.arr[child].wt) // R | |
194 child++; // right child is smaller then left child // A | |
195 // L | |
196 if(this.arr[child].wt < e.wt) // I | |
197 this.arr[parent] = this.arr[child]; // move the child up // I | |
198 else // A | |
199 break; // found a place for e | |
200 parent = child; | |
201 } | |
202 | |
203 // either parent childless or child(ren) of parent are greater or eq to e | |
204 this.arr[parent] = e; | |
205 }//downHeap, L.Allison, Comp Sci and Software Engineering, Monash University | |
206 | |
207 | |
208 function topHeap() | |
209 // PRE: this.size > 0 | |
210 { var ans = this.arr[1]; // C | |
211 this.size--; // S | |
212 if(this.size <= 0) return ans; // S | |
213 //else // E | |
214 this.downHeap(this.arr[this.size+1]); | |
215 return ans; | |
216 } | |
217 | |
218 | |
219 function PriorityQ() // A | |
220 { this.arr = new Array(); // NB. never use arr[0] l | |
221 this.size = 0; // so far l | |
222 // i | |
223 this.pushq = upHeap; // s | |
224 this.popq = topHeap; this.downHeap = downHeap; // o | |
225 }//constructor n | |
226 | |
227 | |
228 function Kruskal(G) // L | |
229 // G is a graph implemented by adjacency lists! A | |
230 // return a minimum spanning tree, T l | |
231 { var i; // l | |
232 var T = new Array(); // to be the min' spanning tree i | |
233 // s | |
234 var Q = new PriorityQ(); // o | |
235 // n | |
236 for(i=0; i < G.Vertices; i++)//first make a PriorityQ of all the edges of G | |
237 { var Gi = G.vertex[i]; | |
238 while(Gi != null) // i.e. for each edge {i,v} | |
239 { Q.pushq(new Edge2(i, Gi.v, Gi.wt)); | |
240 Gi = Gi.tl; | |
241 } | |
242 } | |
243 | |
244 var n = 0; // Computer Science | |
245 var P = new Partition(G.Vertices); // M | |
246 P.singletons(); // o | |
247 while(P.size > 1) // the min' spanning tree algorithm proper n | |
248 { if(Q.size <= 0) // G disconnected a | |
249 break; // s | |
250 // h | |
251 var e = Q.popq(); // shortest edge | |
252 if(P.elt[e.v1].setNumber != P.elt[e.v2].setNumber) // U | |
253 { T[n] = e; n++; // n | |
254 P.merge(P.elt[e.v1].setNumber, P.elt[e.v2].setNumber); // i | |
255 } | |
256 } | |
257 | |
258 return T; | |
259 }//Kruskal, NB. can work on adjacency matrix, but is best on sparse graphs. |