tpl_arrayHeap.H

00001 
00002 /*
00003   This file is part of Aleph system
00004 
00005   Copyright (c) 2002, 2003, 2004, 2005, 2006
00006   UNIVERSITY LOS ANDES (ULA) Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA  
00007 
00008   - Center of Studies in Microelectronics & Distributed Systems (CEMISID) 
00009   - ULA Computer Science Department
00010   - FUNDACITE Mérida - Ministerio de Ciencia y Tecnología
00011 
00012   PERMISSION TO USE, COPY, MODIFY AND DISTRIBUTE THIS SOFTWARE AND ITS
00013   DOCUMENTATION IS HEREBY GRANTED, PROVIDED THAT BOTH THE COPYRIGHT
00014   NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES OF THE
00015   SOFTWARE, DERIVATIVE WORKS OR MODIFIED VERSIONS, AND ANY PORTIONS
00016   THEREOF, AND THAT BOTH NOTICES APPEAR IN SUPPORTING DOCUMENTATION.
00017 
00018   Aleph is distributed in the hope that it will be useful, but WITHOUT
00019   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00020   or FITNESS FOR A PARTICULAR PURPOSE.
00021 
00022   UNIVERSIDAD DE LOS ANDES requests users of this software to return to 
00023 
00024   Leandro Leon
00025   CEMISID 
00026   Ed La Hechicera 
00027   3er piso, ala sur
00028   Facultad de Ingenieria 
00029   Universidad de Los Andes 
00030   Merida - REPÚBLICA BOLIVARIANA DE VENEZUELA    or
00031 
00032   lrleon@ula.ve
00033 
00034   any improvements or extensions that they make and grant Universidad 
00035   de Los Andes (ULA) the rights to redistribute these changes. 
00036 
00037   Aleph is (or was) granted by: 
00038   - Consejo de Desarrollo Cientifico, Humanistico, Tecnico de la ULA 
00039     (CDCHT)
00040   - Fundacite Mérida
00041 */
00042 
00043 
00044 # ifndef TPL_ARRAYHEAP_H
00045 # define TPL_ARRAYHEAP_H
00046 
00047 # include <ahFunction.H>
00048 # include <ahUtils.H>
00049 # include <ahDefs.H>
00050 # include <ahAssert.H>
00051 
00052 namespace Aleph {
00053 
00054 static size_t u_index(const size_t & i)
00055 {
00056   return i >> 1; // divide i entre 2
00057 }
00058 static size_t l_index(const size_t & i)
00059 {
00060   return i << 1; // multiplica i por 2
00061 }
00062     template <typename T, class Compare> inline
00063 void sift_up(T * ptr, const size_t & l, const size_t & r)
00064 {
00065    size_t i, p;
00066 
00067     for (i = r; i > l; i = p) 
00068       {
00069         p = u_index(i); // índice del padre (c = i/2)
00070 
00071         if (Compare () (ptr[p], ptr[i])) // ¿satisface propiedad orden?
00072           return; // si, todo el arreglo es un heap
00073 
00074         Aleph::swap(ptr[p], ptr[i]); // intercambie y restaure en nivel p
00075       }
00076 }
00077     template <typename T, class Compare> inline
00078 void sift_down(T * ptr, const size_t & l, const size_t & r)
00079 {
00080    size_t i = l, c;
00081 
00082    while (true)
00083       {
00084         c = l_index(i); // índice del hijo izquierdo (c = i/2)
00085 
00086         if (c > r) // ¿hay hijo izquierdo?
00087           return; // no ==> termine
00088 
00089         if (c + 1 <= r) // ¿hay hijo derecho?
00090           if (Compare () (ptr[c + 1], ptr[c])) // sí ==> escoja el menor
00091             c++;
00092 
00093         if (Compare () (ptr[i], ptr[c])) // ¿Satisface propiedad de orden?
00094           return;  // sí ==> termine
00095 
00096         Aleph::swap(ptr[c], ptr[i]); 
00097         i = c;
00098       }
00099 }
00100     template <typename T, class Compare> inline
00101 void sift_down_up(T * ptr, const size_t & l, const size_t & i, const size_t & r)
00102 {
00103   sift_down <T, Compare> (ptr, i, r);
00104   sift_up <T, Compare> (ptr, 1, i);
00105 }
00127     template <typename T, class Compare>
00128 void heapsort(T * array, const size_t & n)
00129 {
00130   --array; //desplazar una posición hacia atrás ==> array[1] == primer elemento
00131 
00132   for (int i = 2; i <= n; ++i)
00133     sift_up <T, Aleph::Inversed_Compare<T, Compare> > (array, 1, i);  
00134 
00135   for (int i = n; i > 1; --i)
00136     {
00137       Aleph::swap(array[1], array[i]); // colocar en la raíz i-ésimo item 
00138       sift_down <T, Aleph::Inversed_Compare<T, Compare> > (array, 1, i - 1);
00139     }
00140 }
00141     template <typename T>
00142 void heapsort(T * array, const size_t & n)
00143 {
00144   heapsort <T, Aleph::less<T> > (array, n); 
00145 }
00167     template <typename T, class Compare>
00168 void faster_heapsort(T * array, const size_t & n)
00169 {
00170   --array; // desplazar una posición hacia atrás ==> array[1] == primer elemento
00171 
00172   for (int i = n/2; i >= 1; --i)
00173     sift_down <T, Aleph::Inversed_Compare<T, Compare> > (array, i, n);
00174 
00175   for (int i = n; i > 1; --i)
00176     {
00177       Aleph::swap(array[1], array[i]); // colocar en la raíz i-ésimo item 
00178       sift_down <T, Aleph::Inversed_Compare<T, Compare> > (array, 1, i - 1);
00179     }
00180 }
00181     template <typename T>
00182 void faster_heapsort(T * array, const size_t & n)
00183 {
00184   faster_heapsort <T, Aleph::less<T> > (array, n); 
00185 }
00188       template <typename T, class Compare>
00189 bool valid_heap(T * array, const size_t & l, const size_t & r) 
00190 {
00191   size_t i;
00192       
00193   for (i = l_index(l) /* i = 2*l */; i <= r; i++)
00194     if (Compare () (array[i], array[u_index (i)]))
00195       break;
00196 
00197   return i > r;
00198 }
00199 
00213     template <typename T, class Compare = Aleph::less<T> >
00214 class ArrayHeap 
00215 {
00216   T * array;
00217   const size_t dim;
00218   size_t       num_items;
00219   static size_t r_index(const size_t & i)
00220   {
00221     return (i << 1) + 1; // multiplica i por 2 y suma 1
00222   }
00223   mutable bool array_allocated;
00224 
00225 public:
00226 
00228   ArrayHeap(const size_t & d = 1024) 
00229     : array(NULL), dim(d), num_items(0), array_allocated(false) 
00230   { 
00231     array = new T [d + 1];
00232     array_allocated = true;
00233   }
00234 
00236   ArrayHeap(T * ptr, const size_t & d) 
00237     : array(ptr), dim(d), num_items(0), array_allocated(false) 
00238   { 
00239     // empty
00240   }
00241 
00243   virtual ~ArrayHeap() 
00244   {
00245     if (array_allocated and array != NULL)
00246       delete [] array;
00247   }
00249   T & top()
00250 
00251     throw(std::exception, std::underflow_error)
00252 
00253   {
00254 
00255     if (num_items == 0)
00256         throw std::underflow_error("Heap is empty");
00257 
00258     return array[1];
00259   }
00269   T & insert(const T & key) throw(std::exception, std::overflow_error)
00270   {
00271     if (num_items >= dim)
00272       throw std::overflow_error("Heap out of capacity"); 
00273       
00274     array[++num_items] = key;  // colocar nuevo elemento
00275     sift_up <T, Compare> (array, 1, num_items); // restaurar propiedad de orden
00276 
00277     return array[num_items];
00278   }
00279 
00289   T getMin() 
00290 
00291     throw(std::exception, std::underflow_error)
00292 
00293   {
00294 
00295     if (num_items == 0)
00296         throw std::underflow_error("Heap is empty");
00297 
00298     T ret_val = array[1];
00299 
00300     array[1] = array[num_items--]; // sobreescribir la raíz con último elemento
00301     sift_down <T, Compare> (array, 1, num_items); // Restaurar propiedad de orden
00302 
00303     return ret_val;
00304   }
00305   const size_t & size() const
00306   {
00307     return num_items;
00308   }
00326   void update(T & data) 
00327   {
00328 
00329     I(&data >= &array[0] and &data <= &array[dim]);
00330 
00331     const size_t i = &data - array;
00332 
00333     sift_down_up <T, Compare> (array, 1, i, num_items);
00334   }
00336   T & operator [] (const size_t & i)
00337   {
00338     return array[i];
00339   }
00340 };
00341 
00342 } // end namespace Aleph
00343 # endif /* TPL_ARRAYHEAP_H */
00344 

Leandro R. León