Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/dataStructures/heaps/DiffHeap.cpp
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
 All Classes Files Functions Variables Typedefs Friends