Grafalgo
Library of useful data structures and algorithms
|
00001 00008 #include "PathSet.h" 00009 00010 #define left(x) pnode[x].left 00011 #define right(x) pnode[x].right 00012 #define p(x) pnode[x].p 00013 #define dcost(x) pnode[x].dcost 00014 #define dmin(x) pnode[x].dmin 00015 00016 namespace grafalgo { 00017 00021 PathSet::PathSet(int size) : Adt(size) { 00022 makeSpace(size); 00023 } 00024 00026 PathSet::~PathSet() { freeSpace(); } 00027 00031 void PathSet::makeSpace(int size) { 00032 try { 00033 pnode = new PathNode[size+1]; 00034 } catch (std::bad_alloc e) { 00035 stringstream ss; 00036 ss << "makeSpace:: insufficient space for " 00037 << size << "index values"; 00038 string s = ss.str(); 00039 throw OutOfSpaceException(s); 00040 } 00041 nn = size; clear(); 00042 } 00043 00045 void PathSet::freeSpace() { 00046 delete [] pnode; 00047 } 00048 00050 void PathSet::clear() { 00051 for (index i = 0; i <= n(); i++) { 00052 left(i) = right(i) = p(i) = dcost(i) = dmin(i) = 0; 00053 } 00054 } 00055 00059 void PathSet::resize(int size) { 00060 freeSpace(); 00061 try { makeSpace(size); } catch(OutOfSpaceException e) { 00062 string s; s = "PathSet::resize::" + e.toString(s); 00063 throw OutOfSpaceException(s); 00064 } 00065 } 00066 00071 void PathSet::expand(int size) { 00072 if (size <= n()) return; 00073 PathSet old(this->n()); old.copyFrom(*this); 00074 resize(size); this->copyFrom(old); 00075 } 00079 void PathSet::copyFrom(const PathSet& source) { 00080 if (&source == this) return; 00081 if (source.n() > n()) resize(source.n()); 00082 else clear(); 00083 00084 for (index x = 1; x <= n(); x++) { 00085 pnode[x] = source.pnode[x]; 00086 } 00087 } 00088 00094 index PathSet::splay(index x) { 00095 while (p(x) != 0) splaystep(x); 00096 return x; 00097 } 00098 00102 void PathSet::splaystep(index x) { 00103 index y = p(x); 00104 if (y == 0) return; 00105 index z = p(y); 00106 if (x == left(left(z)) || x == right(right(z))) 00107 rotate(y); 00108 else if (z != 0) // x is "inner grandchild" 00109 rotate(x); 00110 rotate(x); 00111 } 00112 00117 void PathSet::rotate(index x) { 00118 index y = p(x); if (y == 0) return; 00119 index a, b, c; 00120 if (x == left(y)) { a = left(x); b = right(x); c = right(y); } 00121 else { a = right(x); b = left(x); c = left(y); } 00122 00123 // do the rotation 00124 p(x) = p(y); 00125 if (y == left(p(y))) left(p(x)) = x; 00126 else if (y == right(p(y))) right(p(x)) = x; 00127 if (x == left(y)) { 00128 left(y) = right(x); 00129 if (left(y) != 0) p(left(y)) = y; 00130 right(x) = y; 00131 } else { 00132 right(y) = left(x); 00133 if (right(y) != 0) p(right(y)) = y; 00134 left(x) = y; 00135 } 00136 p(y) = x; 00137 00138 // update dmin, dcost values 00139 dmin(a) += dmin(x); dmin(b) += dmin(x); 00140 00141 dcost(x) = dcost(x) + dmin(x); 00142 cost dmx = dmin(x); 00143 dmin(x) = dmin(y); 00144 00145 dmin(y) = dcost(y); 00146 if (b != 0) dmin(y) = min(dmin(y),dmin(b)+dmx); 00147 if (c != 0) dmin(y) = min(dmin(y),dmin(c)); 00148 dcost(y) = dcost(y) - dmin(y); 00149 00150 dmin(b) -= dmin(y); dmin(c) -= dmin(y); 00151 } 00152 00159 path PathSet::findpath(index i) { 00160 index x; 00161 for (x = i; p(x) != 0; x = p(x)) {} 00162 splay(i); 00163 return x; 00164 } 00165 00170 path PathSet::findtail(path q) { 00171 if (q == 0) return 0; 00172 while (right(q) != 0) q = right(q); 00173 return splay(q); 00174 } 00175 00181 void PathSet::addpathcost(path q, cost x) { dmin(q) += x; } 00182 00188 PathSet::PathCostPair PathSet::findpathcost(path q) { 00189 while (1) { 00190 if (right(q) != 0 && dmin(right(q)) == 0) 00191 q = right(q); 00192 else if (dcost(q) > 0) 00193 q = left(q); 00194 else 00195 break; 00196 } 00197 q = splay(q); 00198 PathCostPair cp(q,dmin(q)); 00199 return cp; 00200 } 00201 00207 path PathSet::findtreeroot(index i) { 00208 while (p(i) != 0) i = p(i); 00209 return i; 00210 } 00211 00220 path PathSet::join(path r, index i, path q) { 00221 cost dmin_i = dmin(i); 00222 left(i) = r; right(i) = q; 00223 if (r == 0 && q == 0) { 00224 ; // do nothing 00225 } else if (r == 0) { 00226 dmin(i) = min(dmin(i),dmin(q)); 00227 dmin(q) -= dmin(i); 00228 p(q) = i; 00229 } else if (q == 0) { 00230 dmin(i) = min(dmin(i),dmin(r)); 00231 dmin(r) -= dmin(i); 00232 p(r) = i; 00233 } else { 00234 dmin(i) = min(dmin(r),min(dmin(i),dmin(q))); 00235 dmin(r) -= dmin(i); dmin(q) -= dmin(i); 00236 p(r) = p(q) = i; 00237 } 00238 dcost(i) = dmin_i - dmin(i); 00239 return i; 00240 } 00241 00248 PathSet::PathPair PathSet::split(index i) { 00249 PathPair pair(0,0); 00250 00251 splay(i); 00252 if (left(i) == 0) 00253 pair.p1 = 0; 00254 else { 00255 pair.p1 = left(i); p(pair.p1) = 0; left(i) = 0; 00256 dmin(pair.p1) += dmin(i); 00257 } 00258 if (right(i) == 0) 00259 pair.p2 = 0; 00260 else { 00261 pair.p2 = right(i); p(pair.p2) = 0; right(i) = 0; 00262 dmin(pair.p2) += dmin(i); 00263 } 00264 dmin(i) += dcost(i); 00265 dcost(i) = 0; 00266 00267 return pair; 00268 } 00269 00276 cost PathSet::nodeCost(index i) const { 00277 cost s; 00278 s = dcost(i); 00279 while (i != 0) { s += dmin(i); i = p(i); } 00280 return s; 00281 } 00282 00288 string& PathSet::path2string(path q, string& s) const { 00289 s = ""; 00290 if (q == 0) return s; 00291 stringstream ss; 00292 ss << path2string(left(q),s); 00293 ss << Adt::item2string(q,s) << ":" << nodeCost(q) << " "; 00294 ss << path2string(right(q),s); 00295 s = ss.str(); 00296 return s; 00297 } 00298 00304 string& PathSet::pathTree2string(path q, string& s) const { 00305 stringstream ss; 00306 s = ""; 00307 if (q == 0) return s; 00308 bool singleton = (left(q) = 0 && right(q) == 0); 00309 if (!singleton) ss << "("; 00310 ss << pathTree2string(left(q),s); 00311 ss << Adt::item2string(q,s) << ":" << nodeCost(q) << " "; 00312 ss << pathTree2string(right(q),s); 00313 if (!singleton) ss << ")"; 00314 s = ss.str(); 00315 return s; 00316 } 00317 00322 string& PathSet::toString(string& s) const { 00323 s = ""; string s1; 00324 for (index i = 1; i <= n(); i++) { 00325 if (p(i) == 0) s += path2string(i,s1) + "\n"; 00326 } 00327 return s; 00328 } 00329 00330 } // ends namespace