Home | Documentation | Download | Platforms | Projects | Mailing Lists | Version History

- Main Page
- Classes
- Files
- Related Pages

# 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 //--------------------------------------------------------------------------

University of Passau - FMI - Theoretical Computer Science

Design © 2002, 2003 Marcus Raitner, University of Passau