OpenMesh
OpenMesh/Tools/Utils/HeapT.hh
Go to the documentation of this file.
00001 /*===========================================================================*\
00002  *                                                                           *
00003  *                               OpenMesh                                    *
00004  *      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen      *
00005  *                           www.openmesh.org                                *
00006  *                                                                           *
00007  *---------------------------------------------------------------------------* 
00008  *  This file is part of OpenMesh.                                           *
00009  *                                                                           *
00010  *  OpenMesh is free software: you can redistribute it and/or modify         * 
00011  *  it under the terms of the GNU Lesser General Public License as           *
00012  *  published by the Free Software Foundation, either version 3 of           *
00013  *  the License, or (at your option) any later version with the              *
00014  *  following exceptions:                                                    *
00015  *                                                                           *
00016  *  If other files instantiate templates or use macros                       *
00017  *  or inline functions from this file, or you compile this file and         *
00018  *  link it with other files to produce an executable, this file does        *
00019  *  not by itself cause the resulting executable to be covered by the        *
00020  *  GNU Lesser General Public License. This exception does not however       *
00021  *  invalidate any other reasons why the executable file might be            *
00022  *  covered by the GNU Lesser General Public License.                        *
00023  *                                                                           *
00024  *  OpenMesh is distributed in the hope that it will be useful,              *
00025  *  but WITHOUT ANY WARRANTY; without even the implied warranty of           *
00026  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            *
00027  *  GNU Lesser General Public License for more details.                      *
00028  *                                                                           *
00029  *  You should have received a copy of the GNU LesserGeneral Public          *
00030  *  License along with OpenMesh.  If not,                                    *
00031  *  see <http://www.gnu.org/licenses/>.                                      *
00032  *                                                                           *
00033 \*===========================================================================*/ 
00034 
00035 /*===========================================================================*\
00036  *                                                                           *             
00037  *   $Revision: 362 $                                                         *
00038  *   $Date: 2011-01-26 10:21:12 +0100 (Mi, 26 Jan 2011) $                   *
00039  *                                                                           *
00040 \*===========================================================================*/
00041 
00060 //=============================================================================
00061 //
00062 //  CLASS HeapT
00063 //
00064 //=============================================================================
00065 
00066 #ifndef OPENMESH_UTILS_HEAPT_HH
00067 #define OPENMESH_UTILS_HEAPT_HH
00068 
00069 
00070 //== INCLUDES =================================================================
00071 
00072 #include "Config.hh"
00073 #include <vector>
00074 #include <OpenMesh/Core/System/omstream.hh>
00075 
00076 //== NAMESPACE ================================================================
00077 
00078 namespace OpenMesh { // BEGIN_NS_OPENMESH
00079 namespace Utils { // BEGIN_NS_UTILS
00080 
00081 //== CLASS DEFINITION =========================================================
00082 
00083 
00092 template <class HeapEntry>
00093 struct HeapInterfaceT
00094 {
00096   bool less(const HeapEntry& _e1, const HeapEntry& _e2);
00097 
00099   bool greater(const HeapEntry& _e1, const HeapEntry& _e2);
00100 
00102   int  get_heap_position(const HeapEntry& _e);
00103 
00105   void set_heap_position(HeapEntry& _e, int _i);
00106 };
00107 
00108 
00109 
00132 template <class HeapEntry, class HeapInterface=HeapEntry>
00133 class HeapT : private std::vector<HeapEntry>
00134 {
00135 private: 
00136   typedef std::vector<HeapEntry>            Base;
00137   
00138 public:
00139 
00141   HeapT() : HeapVector() {}
00142   
00144   HeapT(const HeapInterface& _interface)
00145   : HeapVector(),  interface_(_interface)
00146   {}
00147   
00149   ~HeapT(){};
00150 
00151 
00153   void clear() { HeapVector::clear(); }
00154 
00156   bool empty() const { return HeapVector::empty(); }
00157 
00159   unsigned int size() const { return HeapVector::size(); }
00160 
00162   void reserve(unsigned int _n) { HeapVector::reserve(_n); }
00163 
00165   void reset_heap_position(HeapEntry _h)
00166   { interface_.set_heap_position(_h, -1); }
00167   
00169   bool is_stored(HeapEntry _h)
00170   { return interface_.get_heap_position(_h) != -1; }
00171   
00173   void insert(HeapEntry _h)  
00174   { 
00175     push_back(_h); 
00176     upheap(size()-1); 
00177   }
00178 
00180   HeapEntry front() const
00181   { 
00182     assert(!empty()); 
00183     return entry(0); 
00184   }
00185 
00187   void pop_front()
00188   {    
00189     assert(!empty());
00190     reset_heap_position(entry(0));
00191     if (size() > 1)
00192     {
00193       entry(0, entry(size()-1));
00194       Base::pop_back();
00195       downheap(0);
00196     }
00197     else
00198     {
00199       Base::pop_back();
00200     }
00201   }
00202 
00204   void remove(HeapEntry _h)
00205   {
00206     int pos = interface_.get_heap_position(_h);
00207     reset_heap_position(_h);
00208 
00209     assert(pos != -1);
00210     assert((unsigned int) pos < size());
00211     
00212     // last item ?
00213     if ((unsigned int) pos == size()-1)
00214     {
00215       Base::pop_back();    
00216     }
00217     else 
00218     {
00219       entry(pos, entry(size()-1)); // move last elem to pos
00220       Base::pop_back();
00221       downheap(pos);
00222       upheap(pos);
00223     }
00224   }
00225 
00229   void update(HeapEntry _h)
00230   {
00231     int pos = interface_.get_heap_position(_h);
00232     assert(pos != -1);
00233     assert((unsigned int)pos < size());
00234     downheap(pos);
00235     upheap(pos);
00236   }
00237   
00239   bool check()
00240   {
00241     bool ok(true);
00242     unsigned int i, j;
00243     for (i=0; i<size(); ++i)
00244     {
00245       if (((j=left(i))<size()) && interface_.greater(entry(i), entry(j))) 
00246       {
00247         omerr() << "Heap condition violated\n";
00248         ok=false;
00249       }
00250       if (((j=right(i))<size()) && interface_.greater(entry(i), entry(j)))
00251       {
00252         omerr() << "Heap condition violated\n";
00253         ok=false;
00254       }
00255     }
00256     return ok;
00257   }
00258 
00259 protected:  
00261   HeapInterface interface_;
00262 
00263 private:
00264   // typedef
00265   typedef std::vector<HeapEntry> HeapVector;
00266 
00267   
00269   void upheap(unsigned int _idx);
00270 
00271   
00273   void downheap(unsigned int _idx);
00274 
00275   
00277   inline HeapEntry entry(unsigned int _idx) const
00278   {
00279     assert(_idx < size());
00280     return (Base::operator[](_idx));
00281   }
00282 
00283   
00285   inline void entry(unsigned int _idx, HeapEntry _h) 
00286   {
00287     assert(_idx < size());
00288     Base::operator[](_idx) = _h;
00289     interface_.set_heap_position(_h, _idx);
00290   }
00291 
00292   
00294   inline unsigned int parent(unsigned int _i) { return (_i-1)>>1; }
00296   inline unsigned int left(unsigned int _i)   { return (_i<<1)+1; }
00298   inline unsigned int right(unsigned int _i)  { return (_i<<1)+2; }
00299 
00300 };
00301 
00302 
00303 
00304 
00305 //== IMPLEMENTATION ========================================================== 
00306 
00307 
00308 template <class HeapEntry, class HeapInterface>
00309 void
00310 HeapT<HeapEntry, HeapInterface>::
00311 upheap(unsigned int _idx)
00312 {
00313   HeapEntry     h = entry(_idx);
00314   unsigned int  parentIdx;
00315 
00316   while ((_idx>0) &&
00317          interface_.less(h, entry(parentIdx=parent(_idx))))
00318   {
00319     entry(_idx, entry(parentIdx));
00320     _idx = parentIdx;    
00321   }
00322   
00323   entry(_idx, h);
00324 }
00325   
00326 
00327 //-----------------------------------------------------------------------------
00328 
00329   
00330 template <class HeapEntry, class HeapInterface>
00331 void
00332 HeapT<HeapEntry, HeapInterface>::
00333 downheap(unsigned int _idx)
00334 {
00335   HeapEntry     h = entry(_idx);
00336   unsigned int  childIdx;
00337   unsigned int  s = size();
00338   
00339   while(_idx < s)
00340   {
00341     childIdx = left(_idx);
00342     if (childIdx >= s) break;
00343     
00344     if ((childIdx+1 < s) &&
00345         (interface_.less(entry(childIdx+1), entry(childIdx))))
00346       ++childIdx;
00347     
00348     if (interface_.less(h, entry(childIdx))) break;
00349 
00350     entry(_idx, entry(childIdx));
00351     _idx = childIdx;
00352   }  
00353 
00354   entry(_idx, h);
00355 }
00356 
00357 
00358 //=============================================================================
00359 } // END_NS_UTILS
00360 } // END_NS_OPENMESH
00361 //=============================================================================
00362 #endif // OSG_HEAP_HH defined
00363 //=============================================================================
00364 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines