Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/dataStructures/searchTrees/BalBstSet.cpp
Go to the documentation of this file.
00001 
00008 #include "BalBstSet.h"
00009 
00010 #define left(x) node[x].left
00011 #define right(x) node[x].right
00012 #define p(x) node[x].p
00013 #define kee(x) node[x].kee
00014 #define rank(x) rvec[x]
00015 
00016 namespace grafalgo {
00017 
00021 BalBstSet::BalBstSet(int size) : BstSet(size) {
00022         makeSpace(size);
00023 }
00024 
00026 BalBstSet::~BalBstSet() { freeSpace(); }
00027 
00031 void BalBstSet::makeSpace(int size) {
00032         try {
00033                 rvec = new int[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 BalBstSet::freeSpace() {
00046         delete [] rvec;
00047 }
00048 
00050 void BalBstSet::clear() {
00051         BstSet::clear();
00052         for (index i = 0; i <= n(); i++) {
00053                 rank(i) = 1;
00054         }
00055         rank(0) = 0;
00056 }
00057 
00061 void BalBstSet::resize(int size) {
00062         freeSpace();
00063         BstSet::resize(size);
00064         try { makeSpace(size); } catch(OutOfSpaceException e) {
00065                 string s; s = "BalBstSet::resize::" + e.toString(s);
00066                 throw OutOfSpaceException(s);
00067         }
00068 }
00069 
00074 void BalBstSet::expand(int size) {
00075         if (size <= n()) return;
00076         BalBstSet old(this->n()); old.copyFrom(*this);
00077         resize(size); this->copyFrom(old);
00078 }
00082 void BalBstSet::copyFrom(const BalBstSet& source) {
00083         if (&source == this) return;
00084         if (source.n() > n()) resize(source.n());
00085         else clear();
00086 
00087         BstSet::copyFrom(source);
00088         for (index x = 1; x <= n(); x++) {
00089                 rvec[x] = source.rvec[x];
00090         }
00091 }
00092 
00099 void BalBstSet::swap(index i, index j) {
00100         BstSet::swap(i,j);
00101         int r = rvec[i]; rvec[i] = rvec[j]; rvec[j] = r;
00102 }
00103 
00111 bool BalBstSet::insert(index i, bst& t) {
00112         assert(rank(0) == 0);
00113         BstSet::insert(i,t);
00114         if (t == i) return true;
00115         // rank(i) = 1;
00116         // go up the tree correcting rank violations using promotion
00117         index x = i; index gpx = p(p(x));
00118         while (gpx != 0 && rank(x) == rank(gpx) &&
00119                rank(left(gpx)) == rank(right(gpx))) {
00120                 rank(gpx)++; x = gpx; gpx = p(p(x));
00121         }
00122         if (gpx == 0 || rank(x) != rank(gpx)) return true;
00123         // finish off with a rotation or two
00124         if (x == left(left(gpx)) || x == right(right(gpx))) rotate(p(x));
00125         else { rotate(x); rotate(x); }
00126         if (p(t) != 0) t = p(t);
00127         return true;
00128 }
00129 
00136 void BalBstSet::remove(index i, bst& t) {
00137         assert(rank(0) == 0);
00138         index r, x, px, y, z;
00139         r = (t != i ? t : (right(t) != 0 ? right(t) : left(t)));
00140         // r is a node that will remain close to the root after
00141         // all changes are made
00142 
00143         // remove i from the tree
00144         index j;
00145         if (left(i) != 0 && right(i) != 0) {
00146                 for (j = left(i); right(j) != 0; j = right(j)) {}
00147                 swap(i,j);
00148         }
00149         // now, i has at most one child
00150         j = (left(i) != 0 ? left(i) : right(i));
00151         // j is now the index of the only child that could be non-null
00152         if (j != 0) p(j) = p(i);
00153         if (p(i) != 0) {
00154                      if (i ==  left(p(i)))  left(p(i)) = j;
00155                 else if (i == right(p(i))) right(p(i)) = j;
00156                 j = p(i);
00157         }
00158         p(i) = left(i) = right(i) = 0;
00159 
00160         // now rebalance as needed, by checking for and fixing
00161         // violations on the rank invariant
00162         px = j; rank(i) = 1;
00163         // px is now i's former parent just before i was removed
00164         // or the child of i, if i had no parent
00165         if (px == 0) { t = find(r); return; } // arises if i is only node in s
00166              if (rank(left(px))  < rank(px)-1) x = left(px);
00167         else if (rank(right(px)) < rank(px)-1) x = right(px);
00168         else { t = find(r); return; }
00169         // if we reach here x is a child of px and rank(x) < rank(px)-1
00170         // note: x may be 0
00171         // now move up the tree checking for and fixing
00172         // rank violations between x and its parent
00173         y = sibling(x,px);
00174         // note: rank(x) >= 0, so rank(px) >= 2 and rank(y) >= 1
00175         while (px != 0 && rank(x) < rank(px)-1 && 
00176                 (y == 0 || (rank(y) < rank(px) &&
00177                 rank(left(y)) < rank(y) && rank(right(y)) < rank(y)))) {
00178                 rank(px)--; // creates no violations with y or y's children
00179                 x = px; px = p(x); y = sibling(x,px);
00180         }
00181         if (px == 0) { t = find(r); return; }
00182         // note: x can still be null
00183         if (rank(x) >= rank(px)-1) { t = find(r); return; }
00184         // now, do a few rotations to finish up
00185         if (rank(y) == rank(px)) {
00186                 rotate(y); y = sibling(x,px);
00187                 if (left(y) == 0 && right(y) == 0) {
00188                         rank(px)--; t = find(r); return;
00189                 }
00190         }
00191         z = (x == right(px) ? left(y) : right(y)); // z is furthest nephew of x
00192         if (rank(z) == rank(y)) {
00193                 rotate(y);
00194                 if (y != 0) rank(y) = rank(px);
00195                 rank(px)--;
00196         } else {
00197                 z = sibling(z,y);
00198                 // now z is closest nephew of x
00199                 rotate(z); rotate(z);
00200                 if (z != 0) rank(z) = rank(px);
00201                 rank(px)--;
00202         }
00203         t = find(r); if (rank(0) != 0) cerr << "f\n"; return;
00204 }
00205 
00213 bst BalBstSet::join(bst t1, index i, bst t2) {
00214         Util::fatal("BalBstSet: join not implemented");
00215         return i;
00216 }
00217 
00225 BstSet::BstPair BalBstSet::split(index i, bst t) {
00226         Util::fatal("BalBstSet: split not implemented");
00227         return BstPair(0,0);
00228 }
00229 
00235 string& BalBstSet::node2string(index i, string& s) const {
00236         s = "";
00237         if (i == 0) return s;
00238         stringstream ss;
00239         ss << Adt::item2string(i,s);
00240         if (p(i) == 0) ss << "*";
00241         ss << ":" << key(i) << ":" << rank(i);
00242         s = ss.str();
00243         return s;
00244 }
00245 
00246 } // ends namespace
 All Classes Files Functions Variables Typedefs Friends