00001 #ifndef OPENTISSUE_CORE_CONTAINERS_CONTAINERS_HEAP_H 00002 #define OPENTISSUE_CORE_CONTAINERS_CONTAINERS_HEAP_H 00003 // 00004 // OpenTissue, A toolbox for physical based simulation and animation. 00005 // Copyright (C) 2007 Department of Computer Science, University of Copenhagen 00006 // 00007 #include <OpenTissue/configuration.h> 00008 00009 #include <OpenTissue/core/math/math_constants.h> 00010 00011 #include <list> 00012 #include <map> 00013 #include <cassert> 00014 #include <stdexcept> 00015 00016 namespace OpenTissue 00017 { 00018 namespace containers 00019 { 00020 00052 template<typename feature_type_,typename real_type_> 00053 class Heap 00054 { 00055 public: 00056 00057 typedef real_type_ real_type; 00058 typedef feature_type_ feature_type; 00059 00060 public: 00061 00062 class heap_element 00063 { 00064 protected: 00065 00066 feature_type m_feature; 00067 real_type m_priority; 00068 00069 public: 00070 00071 heap_element(feature_type const & f) 00072 : m_feature(f) 00073 , m_priority( math::detail::highest<real_type>() ) 00074 { } 00075 00076 public: 00077 00078 real_type & priority() { return m_priority; } 00079 feature_type const & get_feature() const { return m_feature; } 00080 00081 public: 00082 00083 operator real_type () { return m_priority; } 00084 00085 }; 00086 00087 protected: 00088 00089 typedef std::list<heap_element> heap_type; 00090 00091 public: 00092 00093 typedef typename heap_type::iterator heap_iterator; 00094 00095 protected: 00096 00097 typedef std::map<feature_type,heap_iterator> lut_type; 00098 typedef typename lut_type::iterator lut_iterator; 00099 typedef typename lut_type::const_iterator const_lut_iterator; 00100 00101 heap_type m_heap; 00102 lut_type m_lut; 00103 00104 public: 00105 00106 Heap() 00107 : m_heap() 00108 , m_lut() 00109 {} 00110 00111 00112 ~Heap() { } 00113 00114 00115 void clear() 00116 { 00117 m_lut.clear(); 00118 m_heap.clear(); 00119 } 00120 00126 std::size_t size() const { return m_heap.size(); } 00127 00139 heap_iterator push(feature_type const & f) 00140 { 00141 heap_iterator i = m_heap.insert(m_heap.end(), heap_element(f) ); 00142 //m_lut[f] = i; //--- Yrk! Copy-constructor from singular iterator!!! 00143 m_lut.insert( std::make_pair(f, i )); 00144 return i; 00145 } 00146 00155 bool erase(feature_type const & f ) 00156 { 00157 if(m_heap.empty()) 00158 { 00159 throw std::logic_error("Heap::erase(): trying to erase from an empty heap!"); 00160 return false; 00161 } 00162 lut_iterator lookup = m_lut.find(f); 00163 if(lookup == m_lut.end()) 00164 { 00165 throw std::invalid_argument("Heap::erase(): feature not in heap!"); 00166 return false; 00167 } 00168 m_heap.erase(lookup->second); 00169 m_lut.erase(lookup); 00170 return true; 00171 } 00172 00180 heap_iterator get_heap_iterator(feature_type const & f) 00181 { 00182 if(m_heap.empty()) 00183 { 00184 throw std::logic_error("Heap::get_heap_iterator(): trying to get element from empty heap!"); 00185 return m_heap.end(); 00186 } 00187 lut_iterator lookup = m_lut.find(f); 00188 if(lookup == m_lut.end()) 00189 { 00190 throw std::invalid_argument("Heap::get_heap_iterator(): feature not in heap!"); 00191 return m_heap.end(); 00192 } 00193 return lookup->second; 00194 } 00195 00209 void heapify(heap_iterator i) 00210 { 00211 // TODO 2006-09-26 KE: Add assertion to test if i belongs to this container 00212 00213 if(m_heap.empty()) 00214 { 00215 throw std::logic_error("Heap::heapify(): trying to heapify an empty heap!"); 00216 return; 00217 } 00218 if(i==m_heap.end()) 00219 { 00220 throw std::out_of_range("Heap::heapify(): can not use end position!"); 00221 return; 00222 } 00223 00224 if(i!=m_heap.begin()) 00225 { 00226 heap_iterator j = i; 00227 --j; 00228 while(i!=m_heap.begin() && j->priority() < i->priority() ) 00229 { 00230 feature_type A = i->get_feature(); 00231 feature_type B = j->get_feature(); 00232 heap_element tmp = *i; 00233 *i = *j; 00234 *j = tmp; 00235 00236 assert( (m_lut.find(A) != m_lut.end()) || !"Heap::heapify(i): A was not stored in lut"); 00237 assert( (m_lut.find(B) != m_lut.end()) || !"Heap::heapify(i): B was not stored in lut"); 00238 00239 m_lut[A] = j; 00240 m_lut[B] = i; 00241 if(j!=m_heap.begin()) 00242 --j; 00243 --i; 00244 } 00245 } 00246 if(i!=m_heap.end()) 00247 { 00248 heap_iterator j = i; 00249 ++j; 00250 while(j!=m_heap.end() && j->priority() > i->priority() ) 00251 { 00252 feature_type A = i->get_feature(); 00253 feature_type B = j->get_feature(); 00254 heap_element tmp = *i; 00255 *i = *j; 00256 *j = tmp; 00257 00258 assert( (m_lut.find(A) != m_lut.end()) || !"Heap::heapify(i): A was not stored in lut"); 00259 assert( (m_lut.find(B) != m_lut.end()) || !"Heap::heapify(i): B was not stored in lut"); 00260 00261 m_lut[A] = j; 00262 m_lut[B] = i; 00263 ++j; 00264 ++i; 00265 } 00266 } 00267 } 00268 00273 void heapify() { m_heap.sort( std::greater<real_type>() ); } 00274 00280 heap_iterator top() { return m_heap.begin(); } 00281 00287 heap_iterator begin() { return m_heap.begin(); } 00288 00294 heap_iterator end() { return m_heap.end(); } 00295 00296 }; 00297 00298 } //End of namespace containers 00299 } //End of namespace OpenTissue 00300 00301 // OPENTISSUE_CORE_CONTAINERS_CONTAINERS_HEAP_H 00302 #endif