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