Home | Documentation | Download | Platforms | Projects | Mailing Lists | Version History
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