Grafalgo
Library of useful data structures and algorithms
|
00001 00009 #include "stdinc.h" 00010 #include "Graph.h" 00011 00012 namespace grafalgo { 00013 00018 Graph::Graph(int numv, int maxe) : Adt(numv), maxEdge(maxe) { 00019 makeSpace(numv,maxe); 00020 } 00021 00022 Graph::~Graph() { freeSpace(); } 00023 00028 void Graph::makeSpace(int numv, int maxe) { 00029 try { 00030 fe = new edge[numv+1]; 00031 evec = new EdgeInfo[maxe+1]; 00032 edges = new SetPair(maxe); 00033 adjLists = new ClistSet(2*maxe+1); 00034 } catch (std::bad_alloc e) { 00035 stringstream ss; 00036 ss << "Graph::makeSpace: insufficient space for " 00037 << numv << "vertices and " << maxe << " edges"; 00038 string s = ss.str(); 00039 throw OutOfSpaceException(s); 00040 } 00041 for (vertex u = 0; u <= numv; u++) fe[u] = 0; 00042 for (edge e = 0; e <= maxe; e++) evec[e].l = 0; 00043 nn = numv; mm = 0; maxEdge = maxe; 00044 } 00045 00047 void Graph::freeSpace() { 00048 delete [] fe; delete [] evec; delete edges; delete adjLists; 00049 } 00050 00056 void Graph::resize(int numv, int maxe) { 00057 freeSpace(); 00058 try { makeSpace(numv,maxe); } catch(OutOfSpaceException e) { 00059 string s; s = "Graph::resize:" + e.toString(s); 00060 throw OutOfSpaceException(s); 00061 } 00062 } 00063 00068 void Graph::expand(int numv, int maxe) { 00069 if (numv <= n() && maxe <= maxEdge) return; 00070 Graph old(this->n(),this->maxEdge); old.copyFrom(*this); 00071 resize(numv,maxe); this->copyFrom(old); 00072 } 00073 00075 void Graph::clear() { while (first() != 0) remove(first()); } 00076 00078 void Graph::copyFrom(const Graph& source) { 00079 if (&source == this) return; 00080 if (source.n() > n() || source.m() > maxEdge) 00081 resize(source.n(),source.m()); 00082 else clear(); 00083 for (edge e = source.first(); e != 0; e = source.next(e)) 00084 join(source.left(e),source.right(e)); 00085 } 00086 00093 edge Graph::join(vertex u, vertex v) { 00094 assert(validVertex(u) && validVertex(v)); 00095 00096 edge e = edges->firstOut(); 00097 edge ee = joinWith(u,v,e); 00098 return ee; 00099 } 00100 00108 edge Graph::joinWith(vertex u, vertex v, edge e) { 00109 if (e == 0 || !edges->isOut(e)) return 0; 00110 edges->swap(e); 00111 00112 // initialize edge information 00113 evec[e].l = u; evec[e].r = v; 00114 00115 // add edge to the adjacency lists 00116 // in the adjLists data structure, each edge appears twice, 00117 // as 2*e and 2*e+1 00118 if (fe[u] != 0) adjLists->join(2*e,fe[u]); 00119 if (fe[v] != 0) adjLists->join(2*e+1,fe[v]); 00120 if (fe[u] == 0) fe[u] = 2*e; 00121 if (fe[v] == 0) fe[v] = 2*e+1; 00122 00123 mm++; 00124 00125 return e; 00126 } 00127 00132 bool Graph::remove(edge e) { 00133 assert(validEdge(e)); 00134 edges->swap(e); 00135 00136 vertex u = evec[e].l; 00137 if (fe[u] == 2*e) 00138 fe[u] = (adjLists->suc(2*e) == 2*e ? 0 : adjLists->suc(2*e)); 00139 u = evec[e].r; 00140 if (fe[u] == 2*e+1) 00141 fe[u] = (adjLists->suc(2*e+1) == 2*e+1 ? 00142 0 : adjLists->suc(2*e+1)); 00143 00144 adjLists->remove(2*e); adjLists->remove(2*e+1); 00145 00146 evec[e].l = 0; 00147 00148 mm--; 00149 return true; 00150 } 00151 00152 // Compare two edges incident to the same endpoint u. 00153 // Return -1 if u's mate in e1 is less than u's mate in e2. 00154 // Return +1 if u's mate in e1 is greater than than u's mate in e2. 00155 // Return 0 if u's mate in e1 is equal to its mate in e2. 00156 int Graph::ecmp(edge e1, edge e2, vertex u) const { 00157 if (mate(u,e1) < mate(u,e2)) return -1; 00158 else if (mate(u,e1) > mate(u,e2)) return 1; 00159 else return 0; 00160 } 00161 00165 void Graph::sortAlist(vertex u) { 00166 edge e; int j, k, p, c; 00167 00168 if (fe[u] == 0) return; // empty list 00169 00170 int *elist = new int[n()+1]; 00171 00172 // copy edges in adjacency list for u into an array 00173 k = 1; elist[k++] = fe[u]; 00174 for (e = adjLists->suc(fe[u]); e != fe[u]; ) { 00175 if (k > n()) 00176 Util::fatal("Graph::sortAlist: adjacency list " 00177 "too long"); 00178 elist[k++] = e; 00179 edge f = e; e = adjLists->suc(e); adjLists->remove(f); 00180 } 00181 k--; 00182 // put edge list in heap-order using mate(u) as key 00183 for (j = k/2; j >= 1; j--) { 00184 // do pushdown starting at position j 00185 e = elist[j]; p = j; 00186 while (1) { 00187 c = 2*p; 00188 if (c > k) break; 00189 if (c+1 <= k && ecmp(elist[c+1]/2,elist[c]/2,u) > 0) 00190 c++; 00191 if (ecmp(elist[c]/2,e/2,u) <= 0) break; 00192 elist[p] = elist[c]; p = c; 00193 } 00194 elist[p] = e; 00195 } 00196 // repeatedly extract the edge with largest mate(u) from heap and 00197 // restore heap order 00198 for (j = k-1; j >= 1; j--) { 00199 e = elist[j+1]; elist[j+1] = elist[1]; 00200 // now largest edges are in positions j+1,...,k 00201 // elist[1,...,j] forms a heap with edge having 00202 // largest mate(u) on top 00203 // pushdown from 1 in this restricted heap 00204 p = 1; 00205 while (1) { 00206 c = 2*p; 00207 if (c > j) break; 00208 if (c+1 <= j && ecmp(elist[c+1]/2,elist[c]/2,u) > 0) 00209 c++; 00210 if (ecmp(elist[c]/2,e/2,u) <= 0) break; 00211 elist[p] = elist[c]; p = c; 00212 } 00213 elist[p] = e; 00214 } 00215 // now elist is sorted by mate(u) 00216 00217 // now rebuild links forming adjacency list for u 00218 for (j = k-1; j >= 1; j--) { 00219 adjLists->join(elist[j],elist[j+1]); 00220 } 00221 fe[u] = elist[1]; 00222 00223 delete [] elist; 00224 } 00225 00227 void Graph::sortAdjLists() { 00228 for (vertex u = 1; u <= n(); u++) sortAlist(u); 00229 } 00230 00237 string& Graph::edge2string(edge e, string& s) const { 00238 return edge2string(e,left(e),s); 00239 } 00240 00247 string& Graph::edge2string(edge e, vertex u, string& s) const { 00248 s = "("; 00249 string s1; 00250 vertex v = mate(u,e); 00251 s += item2string(u,s1) + ","; 00252 s += item2string(v,s1) + ")"; 00253 return s; 00254 } 00255 00261 string& Graph::elist2string(list<int>& elist, string& s) const { 00262 s = ""; 00263 int i = elist.size(); 00264 for (edge e : elist) { 00265 string s1; s += edge2string(e,s1); 00266 if (--i) s += " "; 00267 } 00268 return s; 00269 } 00270 00276 string& Graph::adjList2string(vertex u, string& s) const { 00277 s = ""; 00278 if (firstAt(u) == 0) return s; 00279 int cnt = 0; 00280 string s1; 00281 s += "[" + Adt::item2string(u,s1) + ":"; 00282 for (edge e = firstAt(u); e != 0; e = nextAt(u,e)) { 00283 vertex v = mate(u,e); 00284 s += " " + item2string(v,s1); 00285 if (++cnt >= 20 && nextAt(u,e) != 0) { 00286 s += "\n"; cnt = 0; 00287 } 00288 } 00289 s += "]\n"; 00290 return s; 00291 } 00292 00301 string& Graph::toString(string& s) const { 00302 s = "{\n"; 00303 for (vertex u = 1; u <= n(); u++) { 00304 string s1; s += adjList2string(u,s1); 00305 } 00306 s += "}\n"; 00307 return s; 00308 } 00309 00319 string& Graph::toDotString(string& s) const { 00320 s = "graph G {\n"; 00321 int cnt = 0; 00322 for (edge e = first(); e != 0; e = next(e)) { 00323 vertex u = min(left(e),right(e)); 00324 vertex v = max(left(e),right(e)); 00325 string s1; 00326 s += Adt::item2string(u,s1) + " -- "; 00327 s += Adt::item2string(v,s1) + " ; "; 00328 if (++cnt == 15) { cnt = 0; s += "\n"; } 00329 } 00330 s += "}\n"; 00331 return s; 00332 } 00333 00338 bool Graph::readAdjList(istream& in) { 00339 if (!Util::verify(in,'[')) return 0; 00340 vertex u; 00341 if (!Adt::readItem(in,u)) return 0; 00342 if (u > n()) expand(u,m()); 00343 if (!Util::verify(in,':')) return 0; 00344 while (in.good() && !Util::verify(in,']')) { 00345 vertex v; 00346 if (!Adt::readItem(in,v)) return 0; 00347 if (v > n()) expand(v,m()); 00348 if (m() >= maxEdge) expand(n(),max(1,2*m())); 00349 if (u > v) join(u,v); 00350 } 00351 return in.good(); 00352 } 00353 00360 /* 00361 bool Graph::readEdge(istream& in) { 00362 vertex u, v; 00363 if (!Util::verify(in,'(') || !Adt::readItem(in,u) || 00364 !Util::verify(in,',') || !Adt::readItem(in,v) || 00365 !Util::verify(in,')')) { 00366 return false; 00367 } 00368 if (u < 1 || v < 1) return false; 00369 00370 int numv = n(); int maxe = maxEdge; 00371 if (u > n() || v > n()) numv = max(max(u,v),2*n()); 00372 if (m() >= maxEdge) maxe = 2*maxEdge; 00373 if (numv > n() || maxe > maxEdge) resize(numv,maxe); 00374 00375 if (u < v) join(u,v); 00376 return true; 00377 } 00378 */ 00379 00384 istream& operator>>(istream& in, Graph& g) { 00385 g.clear(); 00386 bool ok = Util::verify(in,'{'); 00387 while (ok && !Util::verify(in,'}')) ok = g.readAdjList(in); 00388 if (!ok) { 00389 string s = "misformatted input for Graph object"; 00390 throw InputException(s); 00391 } 00392 g.sortAdjLists(); 00393 return in; 00394 } 00395 00398 void Graph::scramble() { 00399 int *vp = new int[n()+1]; int *ep = new int[maxEdge+1]; 00400 Util::genPerm(n(),vp); Util::genPerm(maxEdge,ep); 00401 shuffle(vp,ep); 00402 sortAdjLists(); 00403 } 00404 00408 void Graph::shuffle(int vp[], int ep[]) { 00409 vertex u; edge e; 00410 EdgeInfo evec1[maxEdge+1]; 00411 00412 for (e = 1; e <= maxEdge; e++) evec1[e].l = evec1[e].r = 0; 00413 for (e = first(); e != 0; e = next(e)) evec1[e] = evec[e]; 00414 adjLists->clear(); edges->clear(); 00415 for (u = 1; u <= n(); u++) fe[u] = 0; 00416 for (e = 1; e <= maxEdge; e++) { 00417 if (evec1[e].l != 0) 00418 joinWith(vp[evec1[e].l],vp[evec1[e].r],ep[e]); 00419 } 00420 } 00421 00428 void Graph::rgraph(int numv, int nume) { 00429 numv = max(0,numv); nume = max(0,nume); 00430 if (numv > n() || nume > maxEdge) resize(numv,nume); 00431 else clear(); 00432 addEdges(nume); 00433 } 00434 00440 void Graph::addEdges(int nume) { 00441 if (nume <= m()) return; 00442 // build set containing edges already in graph 00443 HashSet edgeSet(nume); 00444 for (edge e = first(); e != 0; e = next(e)) { 00445 vertex u = min(left(e), right(e)); 00446 vertex v = max(left(e), right(e)); 00447 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00448 edgeSet.insert(vpair); 00449 } 00450 00451 // add edges using random sampling of vertex pairs 00452 // stop early if graph gets so dense that most samples 00453 // repeat edges already in graph 00454 while (m() < nume && m()/n() < n()/4) { 00455 vertex u = Util::randint(1,n()); 00456 vertex v = Util::randint(1,n()); 00457 if (u == v) continue; 00458 if (u > v) { vertex w = u; u = v; v = w; } 00459 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00460 if (!edgeSet.member(vpair)) { 00461 edgeSet.insert(vpair); join(u,v); 00462 } 00463 } 00464 if (m() == nume) return; 00465 00466 // if more edges needed, build a vector containing remaining 00467 // "candidate" edges and then sample from this vector 00468 vector<uint64_t> vpVec; 00469 for (vertex u = 1; u < n(); u++) { 00470 for (vertex v = u+1; v <= n(); v++) { 00471 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00472 if (!edgeSet.member(vpair)) vpVec.push_back(vpair); 00473 } 00474 } 00475 // sample remaining edges from vector 00476 unsigned int i = 0; 00477 while (m() < nume && i < vpVec.size()) { 00478 int j = Util::randint(i,vpVec.size()-1); 00479 vertex u = vpVec[j] >> 32; 00480 vertex v = vpVec[j] & 0xffffffff; 00481 join(u,v); vpVec[j] = vpVec[i++]; 00482 } 00483 sortAdjLists(); 00484 } 00485 00493 void Graph::rbigraph(int numv, int nume) { 00494 numv = max(1,numv); nume = max(0,nume); 00495 if (n() < 2*numv || maxEdge < nume) resize(2*numv,nume); 00496 else clear(); 00497 00498 // build set containing edges already in graph 00499 HashSet edgeSet(nume); 00500 for (edge e = first(); e != 0; e = next(e)) { 00501 vertex u = min(left(e), right(e)); 00502 vertex v = max(left(e), right(e)); 00503 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00504 edgeSet.insert(vpair); 00505 } 00506 00507 // add edges using random sampling of vertex pairs 00508 // stop early if graph gets so dense that most samples 00509 // repeat edges already in graph 00510 while (m() < nume && m()/numv < numv/2) { 00511 vertex u = Util::randint(1,numv); 00512 vertex v = Util::randint(1,numv); v += numv; 00513 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00514 if (!edgeSet.member(vpair)) { 00515 edgeSet.insert(vpair); join(u,v); 00516 } 00517 } 00518 if (m() == nume) return; 00519 00520 // if more edges needed, build a vector containing remaining 00521 // "candidate" edges and then sample from this vector 00522 vector<uint64_t> vpVec; 00523 for (vertex u = 1; u <= numv; u++) { 00524 for (vertex v = numv+1; v <= 2*numv; v++) { 00525 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00526 if (!edgeSet.member(vpair)) vpVec.push_back(vpair); 00527 } 00528 } 00529 // sample remaining edges from vector 00530 unsigned int i = 0; 00531 while (m() < nume && i < vpVec.size()) { 00532 int j = Util::randint(i,vpVec.size()-1); 00533 vertex u = vpVec[j] >> 32; 00534 vertex v = vpVec[j] & 0xffffffff; 00535 join(u,v); vpVec[j] = vpVec[i++]; 00536 } 00537 sortAdjLists(); 00538 } 00539 00547 void Graph::rtree(int numv) { 00548 // build a random sequence of n-2 vertex numbers 00549 // these can be interpreted as "edge endpoints" for 00550 // the non-leaf vertices in the tree to be generated; 00551 // as we're doing this, compute the vertex degrees 00552 vertex endpoints[numv-1]; int d[numv+1]; 00553 for (int i = 1; i <= numv; i++) d[i] = 1; 00554 for (int i = 1; i <= numv-2; i++) { 00555 endpoints[i] = Util::randint(1,numv); 00556 d[endpoints[i]]++; 00557 } 00558 // now build a heap containing all leaves in the tree 00559 // being generated 00560 Dheap degOne(numv,2); // vertices with one more edge to go 00561 for (vertex u = 1; u <= numv; u++) { 00562 if (d[u] == 1) degOne.insert(u,u); 00563 } 00564 // construct tree based on Cayley's theorem 00565 for (int i = 1; i <= numv-2; i++) { 00566 vertex u = degOne.deletemin(); 00567 vertex v = endpoints[i]; 00568 join(u,v); 00569 if (--d[v] == 1) degOne.insert(v,v); 00570 } 00571 join(degOne.deletemin(),degOne.deletemin()); 00572 sortAdjLists(); 00573 } 00574 00577 void Graph::rcgraph(int numv, int nume) { 00578 // try standard random graph generation 00579 rgraph(numv,nume); 00580 00581 if (getComponents(NULL) == 1) return; 00582 00583 // graph too sparse for standard method to produce connected graph 00584 // so start over, adding edges to a random tree 00585 clear(); 00586 rtree(numv); 00587 addEdges(nume); 00588 } 00589 00596 edge Graph::getEdge(vertex u, vertex v) const { 00597 for (edge e = firstAt(u); e != 0; e = nextAt(u,e)) 00598 if (mate(u,e) == v) return e; 00599 return 0; 00600 } 00601 00611 int Graph::getComponents(int *component) const { 00612 bool noComp = (component == NULL); 00613 if (noComp) component = new int[n()+1]; 00614 for (vertex u = 1; u <= n(); u++) component[u] = 0; 00615 00616 List q(n()); 00617 int curComp = 0; 00618 vertex s = 1; 00619 while (s <= n()) { 00620 // do a breadth-first search from s, labeling all vertices 00621 // found with the current component number 00622 component[s] = ++curComp; q.addLast(s); 00623 while (!q.empty()) { 00624 vertex u = q.first(); q.removeFirst(); 00625 for (edge e = firstAt(u); e != 0; e = nextAt(u,e)) { 00626 vertex v = mate(u,e); 00627 if (component[v] == 0) { 00628 component[v] = curComp; 00629 q.addLast(v); 00630 } 00631 } 00632 } 00633 // scan ahead to next vertex that has not yet been placed in 00634 // some component 00635 while (s <= n() && component[s] != 0) s++; 00636 } 00637 if (noComp) delete [] component; 00638 return curComp; 00639 } 00640 00641 } // ends namespace