Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/dataStructures/advanced/PathSet.cpp
Go to the documentation of this file.
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
 All Classes Files Functions Variables Typedefs Friends