bin_heap.h

00001 //==========================================================================
00002 //
00003 //   bin_heap.h
00004 //
00005 //==========================================================================
00006 // $Id: bin_heap.h,v 1.10 2003/01/07 07:01:05 chris Exp $
00007 
00008 #ifndef GTL_BIN_HEAP_H
00009 #define GTL_BIN_HEAP_H
00010 
00011 #include <GTL/GTL.h>
00012 
00013 #include <cassert>
00014 #include <vector>
00015 #include <map>
00016 
00017 __GTL_BEGIN_NAMESPACE
00018 
00023 template <class T>
00024 class heap_node
00025 {
00026 public:
00031     heap_node()
00032     {
00033     }
00034 
00038     heap_node(const T& n) : data(n)
00039     {
00040     }
00041 
00046     T data;
00047 
00052     int pos;
00053 };
00054 
00055     
00061 template <class T, class Pred>
00062 class bin_heap
00063 {
00064 public:
00070     bin_heap(const Pred& prd);
00071 
00078     bin_heap(const Pred& prd, const int est_size);
00079 
00085     bin_heap(const bin_heap<T, Pred>& bh);
00086 
00097     bin_heap<T, Pred>& operator=(const bin_heap<T, Pred>& bh);
00098     
00102     ~bin_heap();
00103 
00109     void push(const T& ins);
00110 
00114     void pop();
00115 
00121     const T& top() const;
00122     
00135     void changeKey(const T& cha);
00136 
00142     bool is_empty() const;
00143 
00148     void clear();
00149 private:
00154     const Pred& prd;
00155 
00160     int size;
00161 
00167     int capacity;
00168 
00173     vector<heap_node<T>* > container;
00174 
00179     map<T, heap_node<T>* > heap_node_map;
00180 
00185     void bubble_up(heap_node<T>* const n);
00186 
00191     void bubble_down(heap_node<T>* const n);
00192 #ifdef _DEBUG
00193 public:
00198     void print_data_container();
00199 #endif  // _DEBUG
00200 };
00201 
00202 // Implementation Begin
00203 
00204 template <class T, class Pred>
00205 bin_heap<T, Pred>::bin_heap(const Pred& prd) :
00206     prd(prd), size(0), capacity(50)
00207 {
00208     container.resize(capacity);
00209 }
00210 
00211 
00212 template <class T, class Pred>
00213 bin_heap<T, Pred>::bin_heap(const Pred& prd, const int est_size) :
00214     prd(prd), size(0), capacity(50)
00215 {
00216     if (est_size > 50)
00217     {
00218         capacity = est_size;
00219     }
00220     container.resize(capacity);
00221 }
00222 
00223 
00224 template <class T, class Pred>
00225 bin_heap<T, Pred>::bin_heap(const bin_heap<T, Pred>& bh) :
00226     prd(bh.prd), size(bh.size), capacity(bh.capacity)
00227 {
00228     container.resize(capacity);
00229     for (int i = 0; i < size; ++i)
00230     {
00231         container[i] = new heap_node<T>(bh.container[i]->data);
00232     }
00233 }
00234 
00235 
00236 template <class T, class Pred>
00237 bin_heap<T, Pred>& bin_heap<T, Pred>::operator=(const bin_heap<T, Pred>& bh)
00238 {
00239     if (this != &bh)    // no self assignment
00240     {
00241         assert(&prd == &(bh.prd));
00242         clear();
00243         size = bh.size;
00244         capacity = bh.capacity;
00245         container.resize(capacity);
00246         for (int i = 0; i < size; ++i)
00247         {
00248             container[i] = new heap_node<T>(bh.container[i]->data);
00249         }
00250     }
00251     return *this;
00252 }
00253 
00254 
00255 template <class T, class Pred>
00256 bin_heap<T, Pred>::~bin_heap()
00257 {
00258     clear();
00259 }
00260 
00261 
00262 template <class T, class Pred>
00263 void bin_heap<T, Pred>::push(const T& ins)
00264 {
00265     if (size == capacity)
00266     {
00267          // dynamic memory allocation
00268         capacity *= 2;
00269         container.resize(capacity);
00270     }
00271     heap_node<T>* n = new heap_node<T>(ins);
00272     n->pos = size;
00273     container[size] = n;
00274     heap_node_map[ins] = n;
00275     ++size;
00276     bubble_up(n);
00277 }
00278 
00279 
00280 template <class T, class Pred>
00281 void bin_heap<T, Pred>::pop() 
00282 {
00283     assert(size > 0);
00284     // save smallest element for return (ensured by heap condition)
00285     heap_node_map.erase(container[0]->data);
00286     delete container[0];
00287     // replace by last element in array and decrease heap "size"
00288     if (size > 1)
00289     {
00290         container[0] = container[--size];
00291         container[0]->pos = 0;
00292         // reorder heap to ensure heap conditions
00293         bubble_down(container[0]);
00294     }
00295     else
00296     {
00297         size = 0;
00298     }
00299 }
00300 
00301 
00302 template <class T, class Pred>
00303 const T& bin_heap<T, Pred>::top() const
00304 {
00305     return container[0]->data;
00306 }
00307 
00308 
00309 template <class T, class Pred>
00310 void bin_heap<T, Pred>::changeKey(const T& cha)
00311 {
00312     int pos = heap_node_map[cha]->pos;
00313     heap_node<T>* n = container[pos];
00314     if (pos != 0)
00315     {
00316         heap_node<T>* father = container[(pos - 1) / 2];
00317         if (prd(n->data, father->data))
00318         {
00319             bubble_up(n);
00320             return;
00321         }
00322     }
00323     bubble_down(n);
00324 }
00325 
00326 
00327 template <class T, class Pred>
00328 bool bin_heap<T, Pred>::is_empty() const
00329 {
00330     // empty if if first free index is 0
00331     return size == 0;
00332 }
00333   
00334 
00335 template <class T, class Pred>
00336 void bin_heap<T, Pred>::clear()
00337 {
00338     for (int i = 0; i < size; ++i)
00339     {
00340         delete container[i];
00341     }
00342     size = 0;
00343     heap_node_map.clear();
00344 }
00345 
00346   
00347 template <class T, class Pred>
00348 void bin_heap<T, Pred>::bubble_up(heap_node<T>* const n)
00349 {
00350     int pos = n->pos;
00351     // if we are not already at top AND the parent in heap is more
00352     while ((pos != 0) &&
00353            (prd(n->data, container[(pos - 1) / 2]->data)))
00354     {
00355         // move father down
00356         container[pos] = container[(pos - 1) / 2];
00357         container[pos]->pos = pos;
00358         // increment k to parent index
00359         pos = (pos - 1) / 2;
00360     }
00361     // place value in its highest position in heap
00362     container[pos] = n;
00363     container[pos]->pos = pos;
00364 }
00365 
00366 
00367 template <class T, class Pred>
00368 void bin_heap<T, Pred>::bubble_down(heap_node<T>* const n)
00369 {
00370     int pos = n->pos;
00371     int j = 0;
00372     while (pos < size / 2)
00373     {
00374         j = 2 * pos + 1;
00375         // if right child is smaller than left child get right child
00376         if ((j < size - 1) &&
00377             (prd(container[j + 1]->data, container[j]->data)))
00378         {
00379             ++j;
00380         }
00381         // if element is less or equal than its child leave it here
00382         if (!prd(container[j]->data, n->data))
00383         {
00384             break;
00385         }
00386         // else move its child up
00387         container[pos] = container[j];
00388         container[pos]->pos = pos;
00389         // repeat for new position
00390         pos = j;
00391     }
00392     // place element into position, where heap condition is fulfilled
00393     container[pos] = n;
00394     container[pos]->pos = pos;
00395 }
00396   
00397 #ifdef _DEBUG
00398 template <class T, class Pred>
00399 void bin_heap<T, Pred>::print_data_container()
00400 {
00401     if (size == 0)
00402     {
00403         cout << "empty";
00404     }
00405     else
00406     {
00407         for (int pos = 0; pos < size; ++pos)
00408         {
00409             cout << container[pos]->data << " ";
00410         }
00411     }
00412     cout << endl;
00413 }
00414 #endif  // _DEBUG
00415 
00416 // Implementation End
00417 
00418 __GTL_END_NAMESPACE
00419 
00420 #endif  // GTL_BIN_HEAP_H
00421 
00422 //--------------------------------------------------------------------------
00423 //   end of file
00424 //--------------------------------------------------------------------------