Grafalgo
Library of useful data structures and algorithms
|
00001 00009 #include "DiffHeap.h" 00010 00011 #define p(x) ((x)/2) 00012 #define left(x) (2*(x)) 00013 #define right(x) (2*(x)+1) 00014 00015 namespace grafalgo { 00016 00021 DiffHeap::DiffHeap(int size) : Adt(size) { 00022 makeSpace(size); 00023 } 00024 00026 DiffHeap::~DiffHeap() { freeSpace(); } 00027 00031 void DiffHeap::makeSpace(int size) { 00032 try { 00033 h = new index[size+1]; pos = new int[size+1]; 00034 dkey = new keytyp[size+1]; 00035 } catch (std::bad_alloc e) { 00036 stringstream ss; 00037 ss << "makeSpace:: insufficient space for " 00038 << size << "index values"; 00039 string s = ss.str(); 00040 throw OutOfSpaceException(s); 00041 } 00042 for (int i = 1; i <= size; i++) pos[i] = 0; 00043 h[0] = pos[0] = 0; dkey[0] = 0; 00044 hn = 0; nn = size; 00045 } 00046 00048 void DiffHeap::freeSpace() { delete [] h; delete [] pos; delete [] dkey; } 00049 00051 void DiffHeap::copyFrom(const DiffHeap& source) { 00052 if (&source == this) return; 00053 if (source.n() > n()) resize(source.n()); 00054 else clear(); 00055 for (int p = 1; p <= source.hn; p--) { 00056 index x = source.h[p]; 00057 h[p] = x; pos[x] = p; dkey[x] = source.dkey[x]; 00058 } 00059 } 00060 00065 void DiffHeap::resize(int size) { 00066 freeSpace(); 00067 try { makeSpace(size); } catch(OutOfSpaceException e) { 00068 string s; s = "DiffHeap::resize::" + e.toString(s); 00069 throw OutOfSpaceException(s); 00070 } 00071 } 00072 00077 void DiffHeap::expand(int size) { 00078 if (size <= n()) return; 00079 DiffHeap old(this->n()); old.copyFrom(*this); 00080 resize(size); this->copyFrom(old); 00081 } 00082 00084 void DiffHeap::clear() { 00085 for (int x = 1; x <= hn; x++) pos[h[x]] = 0; 00086 hn = 0; 00087 } 00088 00093 inline keytyp DiffHeap::key(index i) const { 00094 keytyp s = 0; x = pos[i]; 00095 while (x != 0) s += dkey[h[x]] 00096 return s; 00097 } 00098 00103 void DiffHeap::insert(index i, keytyp k) { 00104 hn++; siftup(i,k,hn,key(p(hn)); 00105 } 00106 00110 void DiffHeap::remove(index i) { 00111 int j = h[hn--]; 00112 if (i != j) { 00113 keytyp ki = key(i); keytyp kj = key(j); 00114 if (kj <= ki) siftup(j,kj,pos[i]); 00115 else siftdown(j,kj,pos[i]); 00116 } 00117 pos[i] = 0; 00118 } 00119 00130 void DiffHeap::siftup(index i, keytyp ki, int x, keytyp kx) { 00131 int px = p(x); 00132 while (x > 1 && ki < kpx) { 00133 h[x] = h[px]; pos[h[x]] = x; 00134 x = px; px = p(x); 00135 siftupCount++; 00136 } 00137 h[x] = i; pos[i] = x; 00138 } 00139 00145 void DiffHeap::siftdown(index i, int x) { 00146 int cx = minchild(x); 00147 while (cx != 0 && kee[h[cx]] < kee[i]) { 00148 h[x] = h[cx]; pos[h[x]] = x; 00149 x = cx; cx = minchild(x); 00150 siftdownCount += d; 00151 } 00152 h[x] = i; pos[i] = x; 00153 } 00154 00161 int DiffHeap::minchild(int x) { 00162 int y; int minc = left(x); 00163 if (minc > hn) return 0; 00164 for (y = minc + 1; y <= right(x) && y <= hn; y++) { 00165 if (kee[h[y]] < kee[h[minc]]) minc = y; 00166 } 00167 return minc; 00168 } 00169 00174 void DiffHeap::changekey(index i, keytyp k) { 00175 changekeyCount++; 00176 keytyp ki = kee[i]; kee[i] = k; 00177 if (k == ki) return; 00178 if (k < ki) siftup(i,pos[i]); 00179 else siftdown(i,pos[i]); 00180 } 00181 00186 string& DiffHeap::toString(string& s) const { 00187 s = ""; 00188 for (int i = 1; i <= hn; i++) { 00189 string s1; 00190 s += "(" + Adt::item2string(h[i],s1); 00191 s += "," + Adt::item2string(kee[h[i]],s1) + ") "; 00192 if ((i%10) == 0) s += "\n"; 00193 } 00194 if ((hn%10) != 0) s += "\n"; 00195 return s; 00196 } 00197 00199 void DiffHeap::clearStats() { 00200 siftupCount = siftdownCount = changekeyCount = 0; 00201 } 00202 00207 string& DiffHeap::stats2string(string& s) const { 00208 stringstream ss; 00209 ss << "changekeyCount = " << changekeyCount << " "; 00210 ss << "siftupCount = " << siftupCount << " "; 00211 ss << "siftdownCount = " << siftdownCount; 00212 s = ss.str(); 00213 return s; 00214 } 00215 00216 } // ends namespace