summaryrefslogtreecommitdiff
path: root/src/heap.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/heap.h')
-rw-r--r--src/heap.h322
1 files changed, 309 insertions, 13 deletions
diff --git a/src/heap.h b/src/heap.h
index ca12a42..9df4121 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -18,6 +18,25 @@ namespace Bu
18{ 18{
19 subExceptionDecl( HeapException ); 19 subExceptionDecl( HeapException );
20 20
21 /**
22 * A priority queue that allows for an unlimited number of priorities. All
23 * objects enqueued must support less-than-comparison. Then every time an
24 * item is dequeued it is always the least item in the heap. The heap
25 * operates using a binary tree for storage, which allows most operations
26 * to be very fast. Enqueueing and dequeueing are both O(log(N)) operatoins
27 * whereas peeking is constant time.
28 *
29 * This heap implementation allows iterating, however please note that any
30 * enqueue or dequeue operation will invalidate the iterator and make it
31 * unusable (if it still works, you shouldn't trust the results). Also,
32 * the items are not stored in memory in order, they are optomized into a
33 * tree. This means that the items will be in effectively random order
34 * while iterating through them, and the order cannot be trusted. Also,
35 * modifying an item in the heap will not cause that item to be re-sorted.
36 * If you want to change the position of an item in the heap you will have
37 * to dequeue every item before it, dequeue that item, change it, and
38 * re-enqueue all of the items removed.
39 */
21 template<typename item, typename cmpfunc=__basicLTCmp<item>, typename itemalloc=std::allocator<item> > 40 template<typename item, typename cmpfunc=__basicLTCmp<item>, typename itemalloc=std::allocator<item> >
22 class Heap : public Queue<item> 41 class Heap : public Queue<item>
23 { 42 {
@@ -165,29 +184,306 @@ namespace Bu
165 return iFill; 184 return iFill;
166 } 185 }
167 186
168 /* 187 class iterator
169 void print( class Formatter &f )
170 { 188 {
171 f << "graph G {" << "\n"; 189 friend class const_iterator;
172 for( int j = 0; j < iFill; j++ ) 190 friend class Heap<item, cmpfunc, itemalloc>;
191 private:
192 Heap<item, cmpfunc, itemalloc> *pHeap;
193 int iIndex;
194
195 iterator( Heap<item, cmpfunc, itemalloc> *pHeap, int iIndex ) :
196 pHeap( pHeap ), iIndex( iIndex )
173 { 197 {
174 if( j*2+1 < iFill )
175 f << " " << j << " -- " << j*2+1 << ";" << "\n";
176 if( j*2+2 < iFill )
177 f << " " << j << " -- " << j*2+2 << ";" << "\n";
178 } 198 }
179 for( int j = 0; j < iFill; j++ ) 199
200 void checkValid()
201 {
202 if( pHeap == NULL )
203 throw Bu::ExceptionBase("Iterator not initialized.");
204 if( iIndex < 0 || iIndex >= pHeap->iFill )
205 throw Bu::ExceptionBase("Iterator out of bounds.");
206 }
207
208 public:
209 iterator() :
210 pHeap( NULL ),
211 iIndex( -1 )
212 {
213 }
214
215 iterator( const iterator &i ) :
216 pHeap( i.pHeap ),
217 iIndex( i.iIndex )
218 {
219 }
220
221 bool operator==( const iterator &oth ) const
222 {
223 return (oth.pHeap == pHeap) && (oth.iIndex == iIndex);
224 }
225
226 bool operator!=( const iterator &oth ) const
227 {
228 return (oth.pHeap != pHeap) || (oth.iIndex != iIndex);
229 }
230
231 item &operator*()
232 {
233 return pHeap->aItem[iIndex];
234 }
235
236 item *operator->()
237 {
238 return &(pHeap->aItem[iIndex]);
239 }
240
241 iterator &operator++()
242 {
243 checkValid();
244 iIndex++;
245 if( iIndex >= pHeap->iFill )
246 iIndex = -1;
247
248 return *this;
249 }
250
251 iterator &operator--()
252 {
253 checkValid();
254 iIndex--;
255
256 return *this;
257 }
258
259 iterator &operator++( int )
180 { 260 {
181 f << " " << j << " [label=\"" << aItem[j] << "\"];" << "\n"; 261 checkValid();
262 iIndex++;
263 if( iIndex >= pHeap->iFill )
264 iIndex = -1;
265
266 return *this;
267 }
268
269 iterator &operator--( int )
270 {
271 checkValid();
272 iIndex--;
273
274 return *this;
275 }
276
277 iterator operator+( int iDelta )
278 {
279 checkValid();
280 iterator ret( *this );
281 ret.iIndex += iDelta;
282 if( ret.iIndex >= pHeap->iFill )
283 ret.iIndex = -1;
284 return ret;
285 }
286
287 iterator operator-( int iDelta )
288 {
289 checkValid();
290 iterator ret( *this );
291 ret.iIndex -= iDelta;
292 if( ret.iIndex < 0 )
293 ret.iIndex = -1;
294 return ret;
295 }
296
297 operator bool()
298 {
299 return iIndex != -1;
300 }
301
302 bool isValid()
303 {
304 return iIndex != -1;
305 }
306
307 iterator &operator=( const iterator &oth )
308 {
309 pHeap = oth.pHeap;
310 iIndex = oth.iIndex;
311 }
312 };
313
314 class const_iterator
315 {
316 friend class Heap<item, cmpfunc, itemalloc>;
317 private:
318 Heap<item, cmpfunc, itemalloc> *pHeap;
319 int iIndex;
320
321 const_iterator( Heap<item, cmpfunc, itemalloc> *pHeap,
322 int iIndex ) :
323 pHeap( pHeap ), iIndex( iIndex )
324 {
325 }
326
327 void checkValid()
328 {
329 if( pHeap == NULL )
330 throw Bu::ExceptionBase("Iterator not initialized.");
331 if( iIndex < 0 || iIndex >= pHeap->iFill )
332 throw Bu::ExceptionBase("Iterator out of bounds.");
182 } 333 }
183 f << "}" << "\n"; 334
184 } */ 335 public:
336 const_iterator() :
337 pHeap( NULL ),
338 iIndex( -1 )
339 {
340 }
341
342 const_iterator( const const_iterator &i ) :
343 pHeap( i.pHeap ),
344 iIndex( i.iIndex )
345 {
346 }
347
348 const_iterator( const iterator &i ) :
349 pHeap( i.pHeap ),
350 iIndex( i.iIndex )
351 {
352 }
353
354 bool operator==( const const_iterator &oth ) const
355 {
356 return (oth.pHeap == pHeap) && (oth.iIndex == iIndex);
357 }
358
359 bool operator!=( const const_iterator &oth ) const
360 {
361 return (oth.pHeap != pHeap) || (oth.iIndex != iIndex);
362 }
363
364 const item &operator*()
365 {
366 return pHeap->aItem[iIndex];
367 }
368
369 const item *operator->()
370 {
371 return &(pHeap->aItem[iIndex]);
372 }
373
374 const_iterator &operator++()
375 {
376 checkValid();
377 iIndex++;
378 if( iIndex >= pHeap->iFill )
379 iIndex = -1;
380
381 return *this;
382 }
383
384 const_iterator &operator--()
385 {
386 checkValid();
387 iIndex--;
388
389 return *this;
390 }
391
392 const_iterator &operator++( int )
393 {
394 checkValid();
395 iIndex++;
396 if( iIndex >= pHeap->iFill )
397 iIndex = -1;
398
399 return *this;
400 }
401
402 const_iterator &operator--( int )
403 {
404 checkValid();
405 iIndex--;
406
407 return *this;
408 }
409
410 const_iterator operator+( int iDelta )
411 {
412 checkValid();
413 const_iterator ret( *this );
414 ret.iIndex += iDelta;
415 if( ret.iIndex >= pHeap->iFill )
416 ret.iIndex = -1;
417 return ret;
418 }
419
420 const_iterator operator-( int iDelta )
421 {
422 checkValid();
423 const_iterator ret( *this );
424 ret.iIndex -= iDelta;
425 if( ret.iIndex < 0 )
426 ret.iIndex = -1;
427 return ret;
428 }
429
430 operator bool()
431 {
432 return iIndex != -1;
433 }
434
435 bool isValid()
436 {
437 return iIndex != -1;
438 }
439
440 const_iterator &operator=( const const_iterator &oth )
441 {
442 pHeap = oth.pHeap;
443 iIndex = oth.iIndex;
444 }
445
446 const_iterator &operator=( const iterator &oth )
447 {
448 pHeap = oth.pHeap;
449 iIndex = oth.iIndex;
450 }
451 };
452
453 iterator begin()
454 {
455 if( iFill == 0 )
456 return end();
457 return iterator( this, 0 );
458 }
459
460 const_iterator begin() const
461 {
462 if( iFill == 0 )
463 return end();
464 return const_iterator( this, 0 );
465 }
466
467 iterator end()
468 {
469 return iterator( this, -1 );
470 }
471
472 const_iterator end() const
473 {
474 return const_iterator( this, -1 );
475 }
476
185 477
186 private: 478 private:
187 void upSize() 479 void upSize()
188 { 480 {
189 item *aNewItems = ia.allocate( iSize*2+1 ); 481 item *aNewItems = ia.allocate( iSize*2+1 );
190// memcpy( aNewItems, aItem, sizeof(item)*iFill ); 482 //
483 // We cannot use a memcopy here because we don't know what kind
484 // of datastructures are being used, we have to copy them one at
485 // a time.
486 //
191 for( int j = 0; j < iFill; j++ ) 487 for( int j = 0; j < iFill; j++ )
192 { 488 {
193 ia.construct( &aNewItems[j], aItem[j] ); 489 ia.construct( &aNewItems[j], aItem[j] );