Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/dataStructures/heaps/DheapSet.cpp
Go to the documentation of this file.
00001 
00009 #include "DheapSet.h"
00010 
00011 namespace grafalgo {
00012 
00017 DheapSet::DheapSet(int size, int maxh, int dd) :
00018                    Adt(size), maxHeap(maxh), d(dd) {
00019         makeSpace(size,maxh,dd);
00020 }
00021 
00022 DheapSet::~DheapSet() { freeSpace(); }
00023 
00027 void DheapSet::makeSpace(int size, int maxh, int dd) {
00028         numNodes = (size/dd) + maxh;
00029         try {
00030                 heaps = new index[numNodes*dd]; // each d-word block is a "node"
00031                 child = new int[numNodes*dd];    // each item in heaps has child
00032                                                 // node
00033                 parent = new int[numNodes];     // note, one per node
00034                 pred = new int[numNodes];       // ditto
00035         
00036                 key = new keytyp[size+1];
00037 
00038                 root = new index[maxh+1];       // values are indices in
00039                                                 // heaps array
00040                 bot = new index[maxh+1];        // ditto
00041                 hSize = new int[maxh+1];
00042         } catch (std::bad_alloc e) {
00043                 stringstream ss;
00044                 ss << "makeSpace:: insufficient space for "
00045                    << size << "index values";
00046                 string s = ss.str();
00047                 throw OutOfSpaceException(s);
00048         }
00049 
00050         nn = size; maxHeap = maxh; d = dd; clear();
00051 }
00052 
00054 void DheapSet::freeSpace() { 
00055         delete [] heaps; delete [] child; delete [] parent;
00056         delete [] pred; delete [] key; delete [] root;
00057         delete [] bot; delete [] hSize;
00058 }
00059 
00061 void DheapSet::copyFrom(const DheapSet& source) {
00062         Util::fatal("DheapSet::copyFrom not implemented.");
00063 }
00064 
00069 void DheapSet::resize(int size, int maxh, int dd) {
00070         freeSpace();
00071         try { makeSpace(size,maxh,dd); } catch(OutOfSpaceException e) {
00072                 string s; s = "DheapSet::resize::" + e.toString(s);
00073                 throw OutOfSpaceException(s);
00074         }
00075 }
00076 
00081 void DheapSet::expand(int size, int maxh, int dd) {
00082         if (size <= n()) return;
00083         DheapSet old(n(),maxHeap,d); old.copyFrom(*this);
00084         resize(size,maxh,dd); this->copyFrom(old);
00085 }
00086 
00088 void DheapSet::clear() {
00089         for (int h = 1; h <= maxHeap; h++) hSize[h] = 0;
00090         for (int p = 0; p < numNodes*d; p++) heaps[p] = 0;
00091 
00092         // build free list using "parent pointer" of each "node"
00093         for (int i = 0; i < numNodes-1; i++)
00094                 parent[i] = (i+1)*d;
00095         parent[numNodes-1] = -1; // use -1 to mark end of list
00096         free = 0;
00097 }
00098 
00105 bool DheapSet::insert(index i, keytyp k, int h) {
00106         key[i] = k;
00107         if (i == 0) return false;
00108         int n = hSize[h]; int r = (n-1)%d;
00109         if (n != 0 && r != d-1) {
00110                 // no new node required
00111                 int p = bot[h] + r + 1;
00112                 child[p] = -1;
00113                 (hSize[h])++;
00114                 siftup(i,p);
00115                 return true;
00116         }
00117         // allocate new node
00118         if (free < 0) return false;
00119         int p = free; free = parent[free/d];
00120         heaps[p] = i; child[p] = -1;
00121         (hSize[h])++;
00122         //for (int j = 1; j < d; j++) heaps[p+j] = 0;
00123         if (n == 0) {
00124                 root[h] = bot[h] = p;
00125                 pred[p/d] = parent[p/d] = -1;
00126                 return true;
00127         }
00128         pred[p/d] = bot[h]; bot[h] = p;
00129 
00130         // now, find the parent node, and set child and parent pointers
00131         int q = pred[p/d] + (d-1);
00132         while (parent[q/d] >= 0  && q%d == d-1)
00133                 q = parent[q/d];
00134         q = ((q%d != d-1) ? q+1 : q - (d-1));
00135         while (child[q] != -1) q = child[q];
00136         child[q] = p; parent[p/d] = q;
00137 
00138         siftup(i,p);
00139         return true;
00140 }
00141 
00142 // Delete and return item with smallest key.
00143 int DheapSet::deleteMin(int h) {
00144         int hn = hSize[h];
00145         if (hn == 0) return 0;
00146         int i, p;
00147         if (hn == 1) {
00148                 p = root[h]; i = heaps[p]; heaps[p] = 0;
00149                 parent[p/d] = free; free = p;
00150                 hSize[h] = 0;
00151                 return i;
00152         }
00153 
00154         p = nodeMinPos(root[h]); i = heaps[p];
00155         if (hn <= d) { // single node with at least 2 items
00156                 heaps[p] = heaps[root[h]+(--hn)];
00157                 heaps[root[h]+hn] = 0;
00158                 hSize[h] = hn;
00159                 return i;
00160         }
00161 
00162         // so, must be at least two nodes
00163         int q = bot[h]; int r = (hn-1)%d;
00164         int j = heaps[q+r]; heaps[q+r] = 0;
00165         (hSize[h])--;
00166         if (r == 0) { // return last node to free list
00167                 if (parent[q/d] >= 0) child[parent[q/d]] = -1;
00168                 bot[h] = pred[q/d];
00169                 parent[q/d] = free; free = q;
00170         }
00171 
00172         // sift the last item down from the top
00173         siftdown(j, p);
00174         return i;
00175 }
00176 
00177 // Shift i up from position p to restore heap order.
00178 void DheapSet::siftup(index i, int p) {
00179         int pp = parent[p/d];
00180         while (pp >= 0 && key[heaps[pp]] > key[i]) {
00181                 heaps[p] = heaps[pp]; p = pp; pp = parent[pp/d];
00182         }
00183         heaps[p] = i;
00184 }
00185 
00186 // Shift i down from position p to restore heap order.
00187 void DheapSet::siftdown(index i, int p) {
00188         int cp = nodeMinPos(child[p]);
00189         while (cp >= 0 && key[heaps[cp]] < key[i]) {
00190                 heaps[p] = heaps[cp]; p = cp;
00191                 cp = nodeMinPos(child[cp]);
00192         }
00193         heaps[p] = i;
00194 }
00195 
00196 // Change the key of the min item in a heap.
00197 void DheapSet::changeKeyMin(keytyp k, int h) {
00198         int p = nodeMinPos(root[h]);
00199         index i = heaps[p]; key[i] = k;
00200         siftdown(i,p);
00201 }
00202 
00203 string& DheapSet::toString(string& s) const {
00204         s = "";
00205         for (int h = 1; h <= maxHeap; h++) {
00206                 string s1;
00207                 if (!empty(h)) s += toString(h,s1) + "\n";
00208         }
00209         return s;
00210 }
00211 
00212 string& DheapSet::toString(int h, string& s) const {
00213         if (hSize[h] == 0) { s = "[]"; return s; }
00214         stringstream ss;
00215 
00216         list<int> nodeList;
00217         for (int p = bot[h]; p != -1; p = pred[p/d])
00218                 nodeList.push_front(p);
00219         int cnt = 0; int numPerRow = 1;
00220         list<int>::iterator lp;
00221         for (lp = nodeList.begin(); lp != nodeList.end(); lp++) {
00222                 int p = *lp;
00223                 int q = p;
00224                 ss << "[";
00225                 while (q < p+d && heaps[q] != 0) {
00226                         if (q > p) ss << " ";
00227                         index i = heaps[q++];
00228                         ss << i << ":" << key[i];
00229                 }
00230                 ss << "] ";
00231                 if (++cnt == numPerRow) {
00232                         ss << "\n"; cnt = 0; numPerRow *= d;
00233                 }
00234         }
00235         if (cnt != 0) ss << "\n";
00236         s = ss.str();
00237         return s;
00238 }
00239 
00240 } // ends namespace
 All Classes Files Functions Variables Typedefs Friends