heap.h

00001 /* MLPACK 0.2
00002  *
00003  * Copyright (c) 2008, 2009 Alexander Gray,
00004  *                          Garry Boyer,
00005  *                          Ryan Riegel,
00006  *                          Nikolaos Vasiloglou,
00007  *                          Dongryeol Lee,
00008  *                          Chip Mappus, 
00009  *                          Nishant Mehta,
00010  *                          Hua Ouyang,
00011  *                          Parikshit Ram,
00012  *                          Long Tran,
00013  *                          Wee Chin Wong
00014  *
00015  * Copyright (c) 2008, 2009 Georgia Institute of Technology
00016  *
00017  * This program is free software; you can redistribute it and/or
00018  * modify it under the terms of the GNU General Public License as
00019  * published by the Free Software Foundation; either version 2 of the
00020  * License, or (at your option) any later version.
00021  *
00022  * This program is distributed in the hope that it will be useful, but
00023  * WITHOUT ANY WARRANTY; without even the implied warranty of
00024  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  * General Public License for more details.
00026  *
00027  * You should have received a copy of the GNU General Public License
00028  * along with this program; if not, write to the Free Software
00029  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00030  * 02110-1301, USA.
00031  */
00038 #ifndef COLLECTIONS_HEAP_H
00039 #define COLLECTIONS_HEAP_H
00040 
00041 #include "fastlib/col/arraylist.h"
00042 //#include "arraylist.h"
00043 
00052 template <typename TKey, typename TValue = Empty>
00053 class MinHeap {
00054   // TODO: A copiable heap probably isn't a bad idea
00055 
00056  public:
00057   typedef TKey Key;
00058   typedef TValue Value;
00059 
00060  private:
00061   struct Entry {
00062     TKey key;
00063     TValue value;
00064 
00065     OBJECT_TRAVERSAL_SHALLOW(Entry) {
00066       OT_OBJ(key);
00067       OT_OBJ(value);
00068     }
00069   };
00070 
00071   ArrayList<Entry> entries_;
00072 
00073   OBJECT_TRAVERSAL(MinHeap) {
00074     OT_OBJ(entries_);
00075   }
00076 
00077  public:
00081   void Init() {
00082     entries_.Init();
00083   }
00084 
00088   bool is_empty() const {
00089     return entries_.size() == 0;
00090   }
00091 
00098   void Put(Key key, Value value) {
00099     Entry entry;
00100 
00101     entries_.PushBack();
00102 
00103     entry.key = key;
00104     entry.value = value;
00105 
00106     WalkUp_(entry, entries_.size() - 1);
00107   }
00108 
00114   Value Pop() {
00115     Value t = entries_[0].value;
00116 
00117     PopOnly();
00118 
00119     return t;
00120   }
00121 
00128   void PopOnly() {
00129     Entry entry;
00130     entries_.PopBackInit(&entry);
00131 
00132     if (likely(entries_.size() != 0)) {
00133       WalkDown_(entry, 0);
00134     }
00135   }
00136 
00140   Value top() const {
00141     return entries_[0].value;
00142   }
00143 
00147   Key top_key() const {
00148     return entries_[0].key;
00149   }
00150   
00154   void set_top(Value v) {
00155     entries_[0].value = v;
00156   }
00157 
00161   index_t size() const {
00162     return entries_.size();
00163   }
00164 
00165  private:
00166   static index_t ChildIndex_(index_t i) {
00167     return (i << 1) + 1;
00168   }
00169 
00170   static index_t ParentIndex_(index_t i) {
00171     return (i - 1) >> 1;
00172   }
00173 
00174   index_t WalkDown_(const Entry& entry, index_t i) {
00175     Key key = entry.key;
00176     Entry *entries = entries_.begin();
00177     index_t last = entries_.size() - 1;
00178 
00179     for (;;) {
00180       index_t c = ChildIndex_(i);
00181 
00182       if (unlikely(c > last)) {
00183         break;
00184       }
00185 
00186       // TODO: This "if" can be avoided if we're more intelligent...
00187       if (likely(c != last)) {
00188         c += entries[c + 1].key < entries[c].key ? 1 : 0;
00189       }
00190 
00191       if (key <= entries[c].key) {
00192         break;
00193       }
00194 
00195       entries[i] = entries[c];
00196       i = c;
00197     }
00198 
00199     entries[i] = entry;
00200 
00201     return i;
00202   }
00203 
00204   index_t WalkUp_(const Entry& entry, index_t i) {
00205     Key key = entry.key;
00206     Entry *entries = entries_.begin();
00207 
00208     for (;;) {
00209       index_t p;
00210 
00211       if (unlikely(i == 0)) {
00212         break; // highly unlikely, we found the best!
00213       }
00214 
00215       p = ParentIndex_(i);
00216 
00217       if (key >= entries[p].key) {
00218         break;
00219       }
00220 
00221       entries[i] = entries[p];
00222 
00223       i = p;
00224     }
00225 
00226     entries[i] = entry;
00227 
00228     return i;
00229   }
00230 };
00231 
00232 #endif
Generated on Mon Jan 24 12:04:37 2011 for FASTlib by  doxygen 1.6.3