Zero  0.1.0
w_heap.h
Go to the documentation of this file.
1 /*<std-header orig-src='shore' incl-file-exclusion='W_HEAP_H'>
2 
3  $Id: w_heap.h,v 1.13 2010/05/26 01:20:25 nhall Exp $
4 
5 SHORE -- Scalable Heterogeneous Object REpository
6 
7 Copyright (c) 1994-99 Computer Sciences Department, University of
8  Wisconsin -- Madison
9 All Rights Reserved.
10 
11 Permission to use, copy, modify and distribute this software and its
12 documentation is hereby granted, provided that both the copyright
13 notice and this permission notice appear in all copies of the
14 software, derivative works or modified versions, and any portions
15 thereof, and that both notices appear in supporting documentation.
16 
17 THE AUTHORS AND THE COMPUTER SCIENCES DEPARTMENT OF THE UNIVERSITY
18 OF WISCONSIN - MADISON ALLOW FREE USE OF THIS SOFTWARE IN ITS
19 "AS IS" CONDITION, AND THEY DISCLAIM ANY LIABILITY OF ANY KIND
20 FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
21 
22 This software was developed with support by the Advanced Research
23 Project Agency, ARPA order number 018 (formerly 8230), monitored by
24 the U.S. Army Research Laboratory under contract DAAB07-91-C-Q518.
25 Further funding for this work was provided by DARPA through
26 Rome Research Laboratory Contract No. F30602-97-2-0247.
27 
28 */
29 
30 #ifndef __W_HEAP_H
31 #define __W_HEAP_H
32 
33 #include "w_defines.h"
34 
35 /* -- do not edit anything above this line -- </std-header>*/
36 
37 #include "w_base.h"
38 
77 template<class T, class Cmp>
78 class Heap {
79 public:
80  Heap(const Cmp& cmpFunction,
81  int initialNumElements = 32);
82 
83  ~Heap();
84 
86  int NumElements() const;
87 
89  T RemoveFirst();
90 
92  T RemoveN(int i);
93 
95  void AddElement(const T& elem);
96 
98  void AddElementDontHeapify(const T& elem);
99 
101  void Heapify();
102 
104  T& First();
105 
107  T& Value(int i);
108 
110  const T& Second() const;
111 
114  void ReplacedFirst();
115 
119  void IncreasedN(int i);
120 
124  void DecreasedN(int i);
125 
127  void CheckHeap() const;
128 
130  void Print(ostream& out) const;
131 
134  bool HeapProperty(int root) const;
135 
136 protected:
138 
140 
142 
143  const Cmp& cmp;
144 
145  int LeftChild(int i) const;
146 
147  int RightChild(int i) const;
148 
149  int RightSibling(int i) const;
150 
151  int Parent(int i) const;
152 
153  void PrintRoot(ostream& out, int rootElem, int indentLevel) const;
154 
155  void CheckHeapRoot(int rootElem) const;
156 
157  // check heap property for entire heap
158  bool HeapProperty(int lower, int upper) const; // check
159  // heap property from lower->upper, inclusive
160 
161  void SiftDown(int rootElem); // fix heap from rootElem
162  // down to bottom of heap
163  void SiftUp(int rootElem); // fix heap from rootElem
164  // to top of heap
165 
166  void GrowElements(int newSize); // accommodate more
167 };
168 
169 
170 // Mappings between children and parent array indices
171 
172 template<class T, class Cmp>
173 inline int Heap<T, Cmp>::LeftChild(int i) const {
174  return 2 * i + 1;
175 }
176 
177 template<class T, class Cmp>
178 inline int Heap<T, Cmp>::RightChild(int i) const {
179  return 2 * i + 2;
180 }
181 
182 template<class T, class Cmp>
183 inline int Heap<T, Cmp>::RightSibling(int i) const {
184  return i + 1;
185 }
186 
187 template<class T, class Cmp>
188 inline int Heap<T, Cmp>::Parent(int i) const {
189  return (i - 1) / 2;
190 }
191 
192 
193 // short inlined functions
194 
195 template<class T, class Cmp>
196 inline void Heap<T, Cmp>::CheckHeap() const {
198 }
199 
200 template<class T, class Cmp>
201 inline int Heap<T, Cmp>::NumElements() const {
202  return numElements;
203 }
204 
205 template<class T, class Cmp>
206 inline void Heap<T, Cmp>::Print(ostream& out) const {
207  PrintRoot(out, 0, 0);
208 }
209 
210 template<class T, class Cmp>
212  SiftDown(0);
213 }
214 
215 template<class T, class Cmp>
216 inline void Heap<T, Cmp>::IncreasedN(int n) {
217  SiftUp(n);
218 }
219 
220 template<class T, class Cmp>
221 inline void Heap<T, Cmp>::DecreasedN(int n) {
222  SiftDown(n);
223 }
224 
225 template<class T, class Cmp>
226 Heap<T, Cmp>::Heap(const Cmp& cmpFunction, int initialNumElements)
227  :
228  numElements(0),
229  maxNumElements(initialNumElements),
230  elements(0),
231  cmp(cmpFunction) {
232  elements = new T[initialNumElements];
233 }
234 
235 template<class T, class Cmp>
237  delete[] elements;
238 }
239 
240 // removes and returns the first element. maintains heap property.
241 // runs in O(log n).
242 template<class T, class Cmp>
244  w_assert9(numElements > 0);
245  T temp = elements[i];
246  bool smaller = cmp.gt(elements[i], elements[--numElements]);
248  if (smaller) {
249  SiftDown(i);
250  } else {
251  SiftUp(i);
252  }
253  return temp;
254 }
255 
256 template<class T, class Cmp>
258  // return RemoveN(0);
259  // This is pretty inefficient in comparisons if only
260  // because we know that when removing the top element,
261  // we're removing the largest one. So we include
262  // an optimized version of RemoveN(i)
263  T temp = elements[0];
264  elements[0] = elements[--numElements];
265  SiftDown(0);
266  return temp;
267 }
268 
269 
270 // returns the First element in the heap.
271 // runs in O(1).
272 
273 template<class T, class Cmp>
275  w_assert9(numElements > 0);
276  return elements[0];
277 }
278 
279 template<class T, class Cmp>
281  w_assert9(i < numElements && i >= 0);
282  return elements[i];
283 }
284 
285 // return the element which would become First if RemoveFirst() were called.
286 // runs in O(1)
287 
288 template<class T, class Cmp>
289 const T& Heap<T, Cmp>::Second() const {
290  w_assert9(numElements > 1);
291  int second = LeftChild(0);
292  if (RightSibling(second) < numElements) {
293  if (cmp.gt(elements[RightSibling(second)], elements[second])) {
294  second = RightSibling(second);
295  }
296  }
297  return elements[second];
298 }
299 
300 
301 // adds a new element to the heap, maintaining the heap property.
302 // runs in O(log n)
303 
304 template<class T, class Cmp>
305 void Heap<T, Cmp>::AddElement(const T& elem) {
306  if (numElements >= maxNumElements) {
308  }
309 
310  int rootElem = numElements++; // get a new slot
311  while (rootElem > 0) {
312  if (cmp.gt(elem, elements[Parent(rootElem)])) {
313  elements[rootElem] = elements[Parent(rootElem)];
314  rootElem = Parent(rootElem);
315  } else {
316  break;
317  }
318  }
319  elements[rootElem] = elem;
320 }
321 
322 
323 // use this to fill the heap initially.
324 // proceed with a call to Heapify() when all elements are added.
325 
326 template<class T, class Cmp>
328  if (numElements >= maxNumElements) {
330  }
331  elements[numElements++] = elem;
332 }
333 
334 
335 // recreates the heap condition.
336 //
337 // assumes the subtrees of rootElem are heaps and that
338 // only rootElem violates the heap condition.
339 //
340 // starts at the rootElem and stops if there is a valid heap.
341 // otherwise it sifts the rootElem down into the tree of the
342 // larger of the children.
343 //
344 // this runs in O(log n).
345 
346 template<class T, class Cmp>
347 void Heap<T, Cmp>::SiftDown(int rootElem) {
348  /*
349  * Assumes: both children are legitimate heaps
350  */
351  if (LeftChild(rootElem) < numElements) {
352  w_assert9(HeapProperty(LeftChild(rootElem)));
353  }
354 
355  if (numElements > 1) {
356  const T rootValue = elements[rootElem];
357  while (rootElem <= Parent(numElements - 1)) {
358  w_assert9(LeftChild(rootElem) < numElements);
359 
360  // find sibling with larger value
361  // Tends to sift down the larger side
362  int child = LeftChild(rootElem);
363  if (RightSibling(child) < numElements) {
364  if (cmp.gt(elements[RightSibling(child)], elements[child])) {
365  child = RightSibling(child);
366  }
367  }
368 
369  // If the larger child is larger than the root, swap the root
370  // with the larger child.
371  if (cmp.gt(elements[child], rootValue)) {
372  elements[rootElem] = elements[child]; // need to swap
373  rootElem = child;
374  } else {
375  break; // done
376  }
377  }
378  elements[rootElem] = rootValue; // complete swap
379  }
380 
381  /*
382  * Now: legit heap from the root on down
383  * Not necessarily for the whole heap, since
384  * we might be in the middle/early stages of
385  * Heapify-ing a new (unordered) heap.
386  */
387  w_assert9(HeapProperty(rootElem));
388 }
389 
390 template<class T, class Cmp>
391 void Heap<T, Cmp>::SiftUp(int rootElem) {
392  /*
393  * Assumes: legit heap on down to just above rootElem
394  */
395  if (rootElem > 0) {
396  w_assert9(HeapProperty(0, Parent(rootElem)));
397  }
398 
399  if (rootElem > 0) {
400  const T rootValue = elements[rootElem];
401  int i = rootElem;
402  while (i > 0) {
403  if (cmp.gt(rootValue, elements[Parent(i)])) {
404  // Swap : move down parent
405  elements[i] = elements[Parent(i)];
406  i = Parent(i);
407  } else {
408  break;
409  }
410  }
411  elements[i] = rootValue; // complete swap
412  }
413  /*
414  * Now: legit down to and including root Elem
415  */
416  w_assert9(HeapProperty(0, rootElem));
417 }
418 
419 
420 // creates a heap out of the unordered elements.
421 //
422 // start at bottom of the heap and form heaps out of all the
423 // elements which have one child, then form heaps out of
424 // these subheaps until the root of the tree is reached.
425 //
426 // this runs in O(n).
427 
428 template<class T, class Cmp>
430  if (NumElements() > 0) {
431  for (int i = Parent(NumElements() - 1); i >= 0; --i) {
432  SiftDown(i);
433  }
434 #if W_DEBUG_LEVEL > 2
435  CheckHeap();
436 #endif
437  }
438 }
439 
440 
441 // Changes the elements array size.
442 
443 template<class T, class Cmp>
444 void Heap<T, Cmp>::GrowElements(int newSize) {
445  w_assert9(newSize >= numElements);
446 
447  T* newElements = new T[newSize];
448  for (int i = 0; i < numElements; ++i) {
449  newElements[i] = elements[i];
450  }
451  delete[] elements;
452  elements = newElements;
453  maxNumElements = newSize;
454 }
455 
456 
457 // Verifies the heap condition of the elements array.
458 
459 template<class T, class Cmp>
460 void Heap<T, Cmp>::CheckHeapRoot(int rootElem) const {
461  if (rootElem < numElements) {
462  if (LeftChild(rootElem) < numElements) {
463  w_assert1(!cmp.gt(elements[LeftChild(rootElem)],
464  elements[rootElem]));
465  CheckHeapRoot(LeftChild(rootElem));
466  }
467  if (RightChild(rootElem) < numElements) {
468  w_assert1(!cmp.gt(elements[RightChild(rootElem)],
469  elements[rootElem]));
470  CheckHeapRoot(RightChild(rootElem));
471  }
472  }
473 }
474 
475 template<class T, class Cmp>
476 bool Heap<T, Cmp>::HeapProperty(int root) const {
477  return HeapProperty(root, numElements);
478 }
479 
480 // Check heap property from [top, bottom) i.e, NOT INCLUDING bottom
481 // but including top.
482 
483 template<class T, class Cmp>
484 bool Heap<T, Cmp>::HeapProperty(int top, int bottom) const {
485  int last = (bottom > numElements) ? numElements : bottom;
486 
487  for (int i = LeftChild(top); i < last; i++) {
488  if (cmp.gt(elements[i], elements[Parent(i)])) {
489  return false;
490  }
491  }
492  return true;
493 }
494 
495 
496 // Prints out the heap in a rotated tree format.
497 
498 template<class T, class Cmp>
499 void Heap<T, Cmp>::PrintRoot(ostream& out, int rootElem, int indentLevel) const {
500  if (rootElem < NumElements()) {
501  cout << elements[rootElem] << endl;
502  PrintRoot(out, LeftChild(rootElem), indentLevel + 1);
503  for (int i = 0; i < indentLevel; i++) {
504  out << ' ';
505  }
506  PrintRoot(out, RightChild(rootElem), indentLevel + 1);
507  }
508 }
509 
510 /*<std-footer incl-file-exclusion='W_HEAP_H'> -- do not edit anything below this line -- */
511 
512 #endif // __W_HEAP_H /*</std-footer>*/
void DecreasedN(int i)
Inform heap that element i must drop in heap to restore heap property. More efficient than general He...
Definition: w_heap.h:221
#define w_assert1(x)
Level 1 should not add significant extra time.
Definition: w_base.h:198
void PrintRoot(ostream &out, int rootElem, int indentLevel) const
Definition: w_heap.h:499
void SiftUp(int rootElem)
Definition: w_heap.h:391
void CheckHeapRoot(int rootElem) const
Definition: w_heap.h:460
const Cmp & cmp
Definition: w_heap.h:143
void AddElement(const T &elem)
Put in heap and recompute to restore heap property.
Definition: w_heap.h:305
int maxNumElements
Definition: w_heap.h:139
int LeftChild(int i) const
Definition: w_heap.h:173
Heap(const Cmp &cmpFunction, int initialNumElements=32)
Definition: w_heap.h:226
General-purpose heap.
Definition: w_heap.h:78
void SiftDown(int rootElem)
Definition: w_heap.h:347
~Heap()
Definition: w_heap.h:236
T * elements
Definition: w_heap.h:141
void ReplacedFirst()
Inform heap that I replaced the top: recompute, but more efficient than Heapify() ...
Definition: w_heap.h:211
int RightSibling(int i) const
Definition: w_heap.h:183
bool HeapProperty(int root) const
Check heap property from given root to the bottom.
Definition: w_heap.h:476
void IncreasedN(int i)
Inform heap that element i must rise in heap to restore heap property. More efficient than general He...
Definition: w_heap.h:216
T RemoveN(int i)
Remove element from the middle.
Definition: w_heap.h:243
void GrowElements(int newSize)
Definition: w_heap.h:444
void CheckHeap() const
Check heap property.
Definition: w_heap.h:196
int Parent(int i) const
Definition: w_heap.h:188
const T & Second() const
Get reference element just below top (do not remove)
Definition: w_heap.h:289
#define w_assert9(x)
changing an assert to an assert9 turns it off.
Definition: w_base.h:243
void Print(ostream &out) const
Dump heap.
Definition: w_heap.h:206
void Heapify()
Recompute to restore heap property.
Definition: w_heap.h:429
T & First()
Get reference to top of heap (do not remove)
Definition: w_heap.h:274
int numElements
Definition: w_heap.h:137
void AddElementDontHeapify(const T &elem)
Put in heap but do NOT recompute to restore heap property.
Definition: w_heap.h:327
T & Value(int i)
Get reference arbitrary element (do not remove)
Definition: w_heap.h:280
#define T
Definition: w_okvl_inl.h:45
T RemoveFirst()
Take top/largest element off.
Definition: w_heap.h:257
int NumElements() const
How many elements in the heap?
Definition: w_heap.h:201
int RightChild(int i) const
Definition: w_heap.h:178