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