Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:19:36

0001 /* This software is distributed under the GNU Lesser General Public License */
0002 //==========================================================================
0003 //
0004 //   bin_heap.h
0005 //
0006 //==========================================================================
0007 // $Id: bin_heap.h,v 1.10 2003/01/07 07:01:05 chris Exp $
0008 
0009 #ifndef GTL_BIN_HEAP_H
0010 #define GTL_BIN_HEAP_H
0011 
0012 #include <GTL/GTL.h>
0013 
0014 #include <cassert>
0015 #include <vector>
0016 #include <map>
0017 
0018 __GTL_BEGIN_NAMESPACE
0019 
0020 /**
0021  * @internal
0022  * Node type of container.
0023  */
0024 template <class T>
0025 class heap_node
0026 {
0027 public:
0028     /**
0029      * @internal
0030      * Default constructor.
0031      */
0032     heap_node()
0033     {
0034     }
0035 
0036     /**
0037      * @internal
0038      */
0039     heap_node(const T& n) : data(n)
0040     {
0041     }
0042 
0043     /**
0044      * @internal
0045      * Data member.
0046      */
0047     T data;
0048 
0049     /**
0050      * @internal
0051      * Position in container.
0052      */
0053     int pos;
0054 };
0055 
0056     
0057 /**
0058  * @brief Binary heap.
0059  *
0060  * @author Christian Bachmaier chris@infosun.fmi.uni-passau.de
0061  */
0062 template <class T, class Pred>
0063 class bin_heap
0064 {
0065 public:
0066     /**
0067      * @brief Creates empty binary heap.
0068      *
0069      * @param prd binary predicate to compare two <code>T</code>s
0070      */
0071     bin_heap(const Pred& prd);
0072 
0073     /**
0074      * @brief Creates empty binary heap.
0075      *
0076      * @param prd binary predicate to compare two @c Ts
0077      * @param est_size estimated maximal size of heap
0078      */
0079     bin_heap(const Pred& prd, const int est_size);
0080 
0081     /**
0082      * @brief Copy constructor.
0083      *
0084      * @param bh binary heap to copy
0085      */
0086     bin_heap(const bin_heap<T, Pred>& bh);
0087 
0088     /**
0089      * @brief Assigns @c bh to this binary heap.
0090      *
0091      * All elements in this heap will be deleted. The predicate of this heap
0092      * must be physically the same as the one of @p bh.
0093      * 
0094      * @param bh binary heap
0095      *
0096      * @return this heap
0097      */
0098     bin_heap<T, Pred>& operator=(const bin_heap<T, Pred>& bh);
0099     
0100     /**
0101      * @brief Destructor.
0102      */
0103     ~bin_heap();
0104 
0105     /**
0106      * @brief Inserts @p ins in heap.
0107      *
0108      * @param ins data element to be inserted
0109      */
0110     void push(const T& ins);
0111 
0112     /**
0113      * @brief Removes the element on top of the heap.
0114      */
0115     void pop();
0116 
0117     /**
0118      * @brief Returns a reference to the element at the top of the heap.
0119      *
0120      * @return top element of the heap
0121      */
0122     const T& top() const;
0123     
0124     /**
0125      * @brief Reconstructs heap condition after changing key value of @p
0126      * cha externally.
0127      *
0128      * @param cha element with changed key value
0129      *
0130      * @note @c changeKey doesn't operate if @p cha is a primitive data
0131      * structure, because it represents its key value itself, or if one
0132      * object is stored more than once in the data structure.
0133      *
0134      * @sa dijkstra
0135      */
0136     void changeKey(const T& cha);
0137 
0138     /**
0139      * @brief Checks if heap is empty.
0140      *
0141      * @return @c true iff empty
0142      */
0143     bool is_empty() const;
0144 
0145     /**
0146      * @internal
0147      * Makes heap empty.
0148      */
0149     void clear();
0150 private:
0151     /**
0152      * @internal
0153      * Binary predicate to compare two <code>T</code>'s.
0154      */
0155     const Pred& prd;
0156 
0157     /**
0158      * @internal
0159      * Next free position in @a container.
0160      */
0161     int size;
0162 
0163     /**
0164      * @internal
0165      * Estimated maximum size of @a container. Initially set to estimated
0166      * size of user in constructor #bin_heap.
0167      */
0168     int capacity;
0169 
0170     /**
0171      * @internal
0172      * Data container.
0173      */
0174     vector<heap_node<T>* > container;
0175 
0176     /**
0177      * @internal
0178      * Mapping between data member T and its heap_node.
0179      */
0180     map<T, heap_node<T>* > heap_node_map;
0181 
0182     /**
0183      * @internal
0184      * Reconstructs heap condition with bubbling up heap_node @p n.
0185      */
0186     void bubble_up(heap_node<T>* const n);
0187 
0188     /**
0189      * @internal
0190      * Reconstructs heap condition with bubbling down heap_node @p n.
0191      */
0192     void bubble_down(heap_node<T>* const n);
0193 #ifdef _DEBUG
0194 public:
0195     /**
0196      * @internal
0197      * Prints @a container for debug purposes.
0198      */
0199     void print_data_container();
0200 #endif  // _DEBUG
0201 };
0202 
0203 // Implementation Begin
0204 
0205 template <class T, class Pred>
0206 bin_heap<T, Pred>::bin_heap(const Pred& prd) :
0207     prd(prd), size(0), capacity(50)
0208 {
0209     container.resize(capacity);
0210 }
0211 
0212 
0213 template <class T, class Pred>
0214 bin_heap<T, Pred>::bin_heap(const Pred& prd, const int est_size) :
0215     prd(prd), size(0), capacity(50)
0216 {
0217     if (est_size > 50)
0218     {
0219     capacity = est_size;
0220     }
0221     container.resize(capacity);
0222 }
0223 
0224 
0225 template <class T, class Pred>
0226 bin_heap<T, Pred>::bin_heap(const bin_heap<T, Pred>& bh) :
0227     prd(bh.prd), size(bh.size), capacity(bh.capacity)
0228 {
0229     container.resize(capacity);
0230     for (int i = 0; i < size; ++i)
0231     {
0232     container[i] = new heap_node<T>(bh.container[i]->data);
0233     }
0234 }
0235 
0236 
0237 template <class T, class Pred>
0238 bin_heap<T, Pred>& bin_heap<T, Pred>::operator=(const bin_heap<T, Pred>& bh)
0239 {
0240     if (this != &bh)    // no self assignment
0241     {
0242     assert(&prd == &(bh.prd));
0243     clear();
0244     size = bh.size;
0245     capacity = bh.capacity;
0246     container.resize(capacity);
0247     for (int i = 0; i < size; ++i)
0248     {
0249         container[i] = new heap_node<T>(bh.container[i]->data);
0250     }
0251     }
0252     return *this;
0253 }
0254 
0255 
0256 template <class T, class Pred>
0257 bin_heap<T, Pred>::~bin_heap()
0258 {
0259     clear();
0260 }
0261 
0262 
0263 template <class T, class Pred>
0264 void bin_heap<T, Pred>::push(const T& ins)
0265 {
0266     if (size == capacity)
0267     {
0268      // dynamic memory allocation
0269     capacity *= 2;
0270     container.resize(capacity);
0271     }
0272     heap_node<T>* n = new heap_node<T>(ins);
0273     n->pos = size;
0274     container[size] = n;
0275     heap_node_map[ins] = n;
0276     ++size;
0277     bubble_up(n);
0278 }
0279 
0280 
0281 template <class T, class Pred>
0282 void bin_heap<T, Pred>::pop() 
0283 {
0284     assert(size > 0);
0285     // save smallest element for return (ensured by heap condition)
0286     heap_node_map.erase(container[0]->data);
0287     delete container[0];
0288     // replace by last element in array and decrease heap "size"
0289     if (size > 1)
0290     {
0291     container[0] = container[--size];
0292     container[0]->pos = 0;
0293     // reorder heap to ensure heap conditions
0294     bubble_down(container[0]);
0295     }
0296     else
0297     {
0298     size = 0;
0299     }
0300 }
0301 
0302 
0303 template <class T, class Pred>
0304 const T& bin_heap<T, Pred>::top() const
0305 {
0306     return container[0]->data;
0307 }
0308 
0309 
0310 template <class T, class Pred>
0311 void bin_heap<T, Pred>::changeKey(const T& cha)
0312 {
0313     int pos = heap_node_map[cha]->pos;
0314     heap_node<T>* n = container[pos];
0315     if (pos != 0)
0316     {
0317     heap_node<T>* father = container[(pos - 1) / 2];
0318     if (prd(n->data, father->data))
0319     {
0320         bubble_up(n);
0321         return;
0322     }
0323     }
0324     bubble_down(n);
0325 }
0326 
0327 
0328 template <class T, class Pred>
0329 bool bin_heap<T, Pred>::is_empty() const
0330 {
0331     // empty if if first free index is 0
0332     return size == 0;
0333 }
0334   
0335 
0336 template <class T, class Pred>
0337 void bin_heap<T, Pred>::clear()
0338 {
0339     for (int i = 0; i < size; ++i)
0340     {
0341     delete container[i];
0342     }
0343     size = 0;
0344     heap_node_map.clear();
0345 }
0346 
0347   
0348 template <class T, class Pred>
0349 void bin_heap<T, Pred>::bubble_up(heap_node<T>* const n)
0350 {
0351     int pos = n->pos;
0352     // if we are not already at top AND the parent in heap is more
0353     while ((pos != 0) &&
0354        (prd(n->data, container[(pos - 1) / 2]->data)))
0355     {
0356     // move father down
0357     container[pos] = container[(pos - 1) / 2];
0358     container[pos]->pos = pos;
0359     // increment k to parent index
0360     pos = (pos - 1) / 2;
0361     }
0362     // place value in its highest position in heap
0363     container[pos] = n;
0364     container[pos]->pos = pos;
0365 }
0366 
0367 
0368 template <class T, class Pred>
0369 void bin_heap<T, Pred>::bubble_down(heap_node<T>* const n)
0370 {
0371     int pos = n->pos;
0372     int j = 0;
0373     while (pos < size / 2)
0374     {
0375     j = 2 * pos + 1;
0376     // if right child is smaller than left child get right child
0377     if ((j < size - 1) &&
0378         (prd(container[j + 1]->data, container[j]->data)))
0379     {
0380         ++j;
0381     }
0382     // if element is less or equal than its child leave it here
0383     if (!prd(container[j]->data, n->data))
0384     {
0385         break;
0386     }
0387     // else move its child up
0388     container[pos] = container[j];
0389     container[pos]->pos = pos;
0390     // repeat for new position
0391     pos = j;
0392     }
0393     // place element into position, where heap condition is fulfilled
0394     container[pos] = n;
0395     container[pos]->pos = pos;
0396 }
0397   
0398 #ifdef _DEBUG
0399 template <class T, class Pred>
0400 void bin_heap<T, Pred>::print_data_container()
0401 {
0402     if (size == 0)
0403     {
0404     cout << "empty";
0405     }
0406     else
0407     {
0408     for (int pos = 0; pos < size; ++pos)
0409     {
0410         cout << container[pos]->data << " ";
0411     }
0412     }
0413     cout << endl;
0414 }
0415 #endif  // _DEBUG
0416 
0417 // Implementation End
0418 
0419 __GTL_END_NAMESPACE
0420 
0421 #endif  // GTL_BIN_HEAP_H
0422 
0423 //--------------------------------------------------------------------------
0424 //   end of file
0425 //--------------------------------------------------------------------------