Grafalgo
Library of useful data structures and algorithms
|
00001 00009 #include "stdinc.h" 00010 #include "Digraph.h" 00011 00012 namespace grafalgo { 00013 00018 Digraph::Digraph(int numv, int maxe) : Graph(numv,maxe) { 00019 makeSpace(numv,maxe); 00020 } 00021 00022 Digraph::~Digraph() { freeSpace(); } 00023 00028 void Digraph::makeSpace(int numv, int maxe) { 00029 try { 00030 fi = new edge[numv+1]; 00031 } catch (std::bad_alloc e) { 00032 stringstream ss; 00033 ss << "Digraph::makeSpace: insufficient space for " 00034 << numv << "vertices and " << maxe << " edges"; 00035 string s = ss.str(); 00036 throw OutOfSpaceException(s); 00037 } 00038 for (vertex u = 0; u <= numv; u++) fi[u] = 0; 00039 nn = numv; 00040 } 00041 00043 void Digraph::freeSpace() { delete [] fi; } 00044 00050 void Digraph::resize(int numv, int maxe) { 00051 freeSpace(); 00052 Graph::resize(numv,maxe); 00053 try { makeSpace(numv,maxe); } catch(OutOfSpaceException e) { 00054 string s; s = "Digraph::resize:" + e.toString(s); 00055 throw OutOfSpaceException(s); 00056 } 00057 } 00058 00063 void Digraph::expand(int numv, int maxe) { 00064 if (numv <= n() && maxe <= maxEdge) return; 00065 Digraph old(this->n(),this->maxEdge); old.copyFrom(*this); 00066 resize(numv,maxe); this->copyFrom(old); 00067 } 00068 00075 edge Digraph::joinWith(vertex u, vertex v, edge e) { 00076 assert(validVertex(u) && validVertex(v)); 00077 00078 if (e == 0 || !edges->isOut(e)) return 0; 00079 edges->swap(e); 00080 00081 // initialize edge information 00082 evec[e].l = u; evec[e].r = v; 00083 00084 // add edge to the adjacency lists 00085 // in the adjLists data structure, each edge appears twice, 00086 // as 2*e and 2*e+1 00087 if (fe[u] == 0) fe[u] = 2*e; 00088 else adjLists->join(2*e,fe[u]); 00089 if (fi[v] == 0) fi[v] = 2*e+1; 00090 else adjLists->join(2*e+1,fi[v]); 00091 00092 mm++; 00093 00094 return e; 00095 } 00096 00101 bool Digraph::remove(edge e) { 00102 assert(validEdge(e)); 00103 edges->swap(e); 00104 00105 vertex u = evec[e].l; 00106 if (fe[u] == 2*e) 00107 fe[u] = (adjLists->suc(2*e) == 2*e ? 0 : adjLists->suc(2*e)); 00108 u = evec[e].r; 00109 if (fi[u] == 2*e+1) 00110 fi[u] = (adjLists->suc(2*e+1) == 2*e+1 ? 00111 0 : adjLists->suc(2*e+1)); 00112 00113 adjLists->remove(2*e); adjLists->remove(2*e+1); 00114 00115 evec[e].l = 0; 00116 00117 mm--; 00118 return true; 00119 } 00120 00126 string& Digraph::adjList2string(vertex u, string& s) const { 00127 s = ""; 00128 if (firstOut(u) == 0) return s; 00129 int cnt = 0; 00130 string s1; 00131 s += "[" + Adt::item2string(u,s1) + ":"; 00132 for (edge e = firstOut(u); e != 0; e = nextOut(u,e)) { 00133 vertex v = head(e); 00134 s += " " + Adt::item2string(v,s1); 00135 if (++cnt >= 20 && nextOut(u,e) != 0) { 00136 s += "\n"; cnt = 0; 00137 } 00138 } 00139 s += "]\n"; 00140 return s; 00141 } 00142 00152 string& Digraph::toDotString(string& s) const { 00153 s = "digraph G {\n"; 00154 int cnt = 0; 00155 for (edge e = first(); e != 0; e = next(e)) { 00156 vertex u = tail(e); vertex v = head(e); 00157 string s1; 00158 s += Adt::item2string(u,s1) + " -> "; 00159 s += Adt::item2string(v,s1) + " ; "; 00160 if (++cnt == 15) { cnt = 0; s += "\n"; } 00161 } 00162 s += "}\n"; 00163 return s; 00164 } 00165 00170 /* 00171 bool Digraph::readEdge(istream& in) { 00172 vertex u, v; 00173 if (!Util::verify(in,'(') || !Adt::readItem(in,u) || 00174 !Util::verify(in,',') || !Adt::readItem(in,v) || 00175 !Util::verify(in,')')) { 00176 return false; 00177 } 00178 if (u < 1 || v < 1) return false; 00179 00180 int numv = n(); int maxe = maxEdge; 00181 if (u > n() || v > n()) numv = max(max(u,v),2*n()); 00182 if (m() >= maxEdge) maxe = 2*maxEdge; 00183 if (numv > n() || maxe > maxEdge) resize(numv,maxe); 00184 00185 join(u,v); 00186 return true; 00187 } 00188 */ 00189 00194 bool Digraph::readAdjList(istream& in) { 00195 if (!Util::verify(in,'[')) return 0; 00196 vertex u; 00197 if (!Adt::readItem(in,u)) return 0; 00198 if (u > n()) expand(u,m()); 00199 if (!Util::verify(in,':')) return 0; 00200 while (in.good() && !Util::verify(in,']')) { 00201 vertex v; 00202 if (!Adt::readItem(in,v)) return 0; 00203 if (v > n()) expand(v,m()); 00204 if (m() >= maxEdge) expand(n(),max(1,2*m())); 00205 join(u,v); 00206 } 00207 return in.good(); 00208 } 00209 00214 /* 00215 istream& operator>>(istream& in, Digraph& dg) { 00216 bool ok = Util::verify(in,'{'); 00217 while (ok && !Util::verify(in,'}')) ok = dg.readEdge(in); 00218 if (!ok) { 00219 string s = "misformatted input for Graph object"; 00220 throw InputException(s); 00221 } 00222 dg.sortAdjLists(); 00223 return in; 00224 } 00225 */ 00226 00233 void Digraph::rgraph(int numv, int nume) { 00234 numv = max(0,numv); nume = max(0,nume); 00235 if (numv > n() || nume > maxEdge) resize(numv,nume); 00236 else clear(); 00237 00238 // build set containing edges already in graph 00239 HashSet edgeSet(nume); 00240 for (edge e = first(); e != 0; e = next(e)) { 00241 vertex u = min(tail(e), head(e)); 00242 vertex v = max(tail(e), head(e)); 00243 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00244 edgeSet.insert(vpair); 00245 } 00246 00247 // add edges using random sampling of vertex pairs 00248 // stop early if graph gets so dense that most samples 00249 // repeat edges already in graph 00250 while (m() < nume && m()/numv < numv/2) { 00251 vertex u = Util::randint(1,numv); 00252 vertex v = Util::randint(1,numv); 00253 if (u == v) continue; 00254 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00255 if (!edgeSet.member(vpair)) { 00256 edgeSet.insert(vpair); join(u,v); 00257 } 00258 } 00259 if (m() == nume) return; 00260 00261 // if more edges needed, build a vector containing remaining 00262 // "candidate" edges and then sample from this vector 00263 vector<uint64_t> vpVec; 00264 unsigned int i = 0; 00265 for (vertex u = 1; u < numv; u++) { 00266 for (vertex v = 1; v <= numv; v++) { 00267 if (v == u) continue; 00268 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00269 if (!edgeSet.member(vpair)) vpVec[i++] = vpair; 00270 } 00271 } 00272 // sample remaining edges from vector 00273 i = 0; 00274 while (m() < nume && i < vpVec.size()) { 00275 int j = Util::randint(i,vpVec.size()-1); 00276 vertex u = vpVec[j] >> 32; 00277 vertex v = vpVec[j] & 0xffffffff; 00278 join(u,v); vpVec[j] = vpVec[i++]; 00279 } 00280 sortAdjLists(); 00281 } 00282 00289 void Digraph::rdag(int numv, int nume) { 00290 numv = max(0,numv); nume = max(0,nume); 00291 if (n() < numv || maxEdge < nume) resize(numv,nume); 00292 else clear(); 00293 00294 // build set containing edges already in graph 00295 HashSet edgeSet(nume); 00296 for (edge e = first(); e != 0; e = next(e)) { 00297 vertex u = min(tail(e), head(e)); 00298 vertex v = max(tail(e), head(e)); 00299 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00300 edgeSet.insert(vpair); 00301 } 00302 00303 // add edges using random sampling of vertex pairs 00304 // stop early if graph gets so dense that most samples 00305 // repeat edges already in graph 00306 while (m() < nume && m()/numv < numv/4) { 00307 vertex u = Util::randint(1,numv-1); 00308 vertex v = Util::randint(u+1,numv); 00309 if (u == v) continue; 00310 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00311 if (!edgeSet.member(vpair)) { 00312 edgeSet.insert(vpair); join(u,v); 00313 } 00314 } 00315 if (m() == nume) return; 00316 00317 // if more edges needed, build a vector containing remaining 00318 // "candidate" edges and then sample from this vector 00319 vector<uint64_t> vpVec; 00320 for (vertex u = 1; u < numv; u++) { 00321 for (vertex v = u+1; v <= numv; v++) { 00322 if (v == u) continue; 00323 uint64_t vpair = u; vpair <<= 32; vpair |= v; 00324 if (!edgeSet.member(vpair)) vpVec.push_back(vpair); 00325 } 00326 } 00327 // sample remaining edges from vector 00328 int i = 0; 00329 while (m() < nume && i < vpVec.size()) { 00330 int j = Util::randint(i,vpVec.size()-1); 00331 vertex u = vpVec[j] >> 32; 00332 vertex v = vpVec[j] & 0xffffffff; 00333 join(u,v); vpVec[j] = vpVec[i++]; 00334 } 00335 sortAdjLists(); 00336 } 00337 00338 } // ends namespace