Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/dataStructures/heaps/FheapSet.cpp
00001 
00008 #include "FheapSet.h"
00009 
00010 namespace grafalgo {
00011 
00012 #define left(x) sibs->pred(x)
00013 #define right(x) sibs->suc(x)
00014 #define kee(x) node[x].kee
00015 #define rank(x) node[x].rank
00016 #define mark(x) node[x].mark
00017 #define p(x) node[x].p
00018 #define c(x) node[x].c
00019 
00023 FheapSet::FheapSet(int size) : Adt(size) { makeSpace(size); }
00024 
00026 FheapSet::~FheapSet() { freeSpace(); }
00027 
00031 void FheapSet::makeSpace(int size) {
00032         try {
00033                 node = new Fnode[size+1];
00034                 sibs = new ClistSet(size);
00035                 tmpq = new List(size);
00036         } catch (std::bad_alloc e) {
00037                 stringstream ss;
00038                 ss << "makeSpace:: insufficient space for "
00039                    << size << "index values";
00040                 string s = ss.str();
00041                 throw OutOfSpaceException(s);
00042         }
00043         nn = size; clear();
00044 }
00045 
00047 void FheapSet::freeSpace() { delete [] node; delete sibs; delete tmpq; }
00048 
00050 void FheapSet::copyFrom(const FheapSet& source) {
00051         if (&source == this) return;
00052         if (source.n() > n()) resize(source.n());
00053         else clear();
00054 
00055         (*sibs).copyFrom(*source.sibs);
00056         for (index x = 1; x <= source.n(); x++) {
00057                 c(x) = source.node[x].c;
00058                 p(x) = source.node[x].p;
00059                 rank(x) = source.node[x].rank;
00060                 kee(x) = source.node[x].kee;
00061                 mark(x) = source.node[x].mark;
00062         }
00063 }
00064 
00069 void FheapSet::resize(int size) {
00070         freeSpace();
00071         try { makeSpace(size); } catch(OutOfSpaceException e) {
00072                 string s; s = "FheapSet::resize::" + e.toString(s);
00073                 throw OutOfSpaceException(s);
00074         }
00075 }
00076 
00081 void FheapSet::expand(int size) {
00082         if (size <= n()) return;
00083         FheapSet old(this->n()); old.copyFrom(*this);
00084         resize(size); this->copyFrom(old);
00085 }
00086 
00088 void FheapSet::clear() {
00089         sibs->clear();
00090         for (index x = 0; x <= n(); x++) {
00091                 c(x) = p(x) = rank(x) = kee(x) = 0; mark(x) = false;
00092         }
00093         for (index x = 0; x <= FheapSet::MAXRANK; x++) rvec[x] = 0;
00094 }
00095 
00102 fheap FheapSet::meld(fheap h1, fheap h2) {
00103         assert(0 <= h1 && h1 <= n() && 0 <= h2 && h2 <= n());
00104         if (h1 == 0) return h2;
00105         if (h2 == 0) return h1;
00106         sibs->join(h1,h2);
00107         return kee(h1) <= kee(h2) ? h1 : h2;
00108 }
00109 
00117 fheap FheapSet::insert(index i, fheap h, keytyp x) {
00118         assert(0 <= i && i <= n() && 0 <= h && h <= n());
00119         setKey(i,x);
00120         return meld(i,h);
00121 }
00122 
00130 fheap FheapSet::decreasekey(index i, keytyp delta, fheap h) {
00131         assert(0 <= i && i <= n() && 0 <= h && h <= n() && delta >= 0);
00132         fheap pi = p(i);
00133         kee(i) -= delta;
00134         if (pi == 0) return kee(i) < kee(h) ? i : h;
00135         c(pi) = rank(pi) == 1 ? 0: left(i);
00136         rank(pi)--;
00137         sibs->remove(i);
00138         p(i) = 0;
00139         h = meld(i,h);
00140         if (p(pi) == 0) return h;
00141         if (!mark(pi))  mark(pi) = true;
00142         else            h = decreasekey(pi,0,h);
00143         return h;
00144 }
00145 
00151 fheap FheapSet::deletemin(fheap h) {
00152         assert(1 <= h && h <= n());
00153         index i,j; int k,mr;
00154 
00155         // Merge h's children into root list and remove it
00156         sibs->join(h,c(h)); c(h) = 0; rank(h) = 0;
00157         if (left(h) == h) return 0;
00158         i = left(h);
00159         sibs->remove(h);
00160         
00161         // Build queue of roots and find root with smallest key
00162         h = i; tmpq->addLast(i); p(i) = 0;
00163         for (j = right(i); j != i; j = right(j)) {
00164                 if (kee(j) < kee(h)) h = j;
00165                 tmpq->addLast(j); p(j) = 0;
00166         }
00167         mr = -1;
00168         while (!tmpq->empty()) {
00169                 // scan roots, merging trees of equal rang
00170                 i = tmpq->first(); tmpq->removeFirst();
00171                 if (rank(i) > FheapSet::MAXRANK)
00172                         Util::fatal("deletemin: rank too large");
00173                 j = rvec[rank(i)];
00174                 if (mr < rank(i)) {
00175                         for (mr++; mr < rank(i); mr++) rvec[mr] = 0;
00176                         rvec[rank(i)] = i;
00177                 } else if (j == 0) {
00178                         rvec[rank(i)] = i;
00179                 } else if (kee(i) < kee(j)) {
00180                         sibs->remove(j);
00181                         sibs->join(c(i),j); c(i) = j;
00182                         rvec[rank(i)] = 0;
00183                         rank(i)++;
00184                         p(j) = i; mark(j) = false;
00185                         tmpq->addLast(i);
00186                 } else {
00187                         sibs->remove(i);
00188                         sibs->join(c(j),i); c(j) = i;
00189                         rvec[rank(i)] = 0;
00190                         rank(j)++;
00191                         p(i) = j; mark(i) = false;
00192                         if (h == i) h = j;
00193                         tmpq->addLast(j);
00194                 }
00195         }
00196         for (k = 0; k <= mr; k++) rvec[k] = 0;
00197         return h;
00198 }
00199 
00205 fheap FheapSet::remove(index i, fheap h) {
00206         assert(1 <= i && i <= n() && 1 <= h && h <= n());
00207         keytyp k;
00208         k = kee(i);
00209         h = decreasekey(i,(kee(i)-kee(h))+1,h);
00210         h = deletemin(h);
00211         kee(i) = k;
00212         return h;
00213 }
00214 
00219 string& FheapSet::toString(string& s) const {
00220         s = "";
00221         bool *pmark = new bool[n()+1];
00222         for (int i = 1; i <= n(); i++) pmark[i] = false;
00223         for (int i = 1; i <= n(); i++) {
00224                 if (p(i) == 0 && !pmark[i]) {
00225                         // i is a root in a new heap
00226                         if (c(i) == 0 && left(i) == i) continue;
00227                         // find minkey item, mark all tree roots in this heap
00228                         pmark[i] = true;
00229                         int k = i;
00230                         for (int j = sibs->suc(i); j != i; j = sibs->suc(j)) {
00231                                 if (key(j) < key(k)) k = j; 
00232                                 pmark[j] = true;
00233                         }
00234                         string s1;
00235                         s += heap2string(k,s1) + "\n";
00236                 }
00237         }
00238         delete [] pmark;
00239         return s;
00240 }
00241 
00247 string& FheapSet::heap2string(fheap h, string& s) const {
00248         s = "";
00249         if (h == 0 || (p(h) == 0 && c(h) == 0 && left(h) == h)) return s;
00250         stringstream ss;
00251         ss << "[" << item2string(h,s) << ":" << kee(h) << "," << rank(h);
00252         if (mark(h)) ss << "*";
00253         ss << heap2string(c(h),s);
00254         for (index i = right(h); i != h; i = right(i)) {
00255                 ss << " " << item2string(i,s) << ":" << kee(i) << "," <<rank(i);
00256                 if (mark(i)) ss << "*";
00257                 ss << heap2string(c(i),s);
00258         }
00259         ss << "]";
00260         s = ss.str();
00261         return s;
00262 }
00263 
00264 } // ends namespace
 All Classes Files Functions Variables Typedefs Friends