Grafalgo
Library of useful data structures and algorithms
|
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